From 328889689f305ddac05134c466e241543583a7d1 Mon Sep 17 00:00:00 2001 From: taizan-hokouto <55448286+taizan-hokuto@users.noreply.github.com> Date: Sat, 24 Jul 2021 21:48:13 +0900 Subject: [PATCH 1/6] Make it possible to use customized client --- pytchat/core/pytchat.py | 62 ++++++++++--------- pytchat/core_async/livechat.py | 20 +++--- pytchat/core_multithread/livechat.py | 15 +++-- pytchat/processors/default/processor.py | 4 +- .../processors/default/renderer/donation.py | 6 ++ pytchat/processors/speed/calculator.py | 43 ++++--------- 6 files changed, 79 insertions(+), 71 deletions(-) create mode 100644 pytchat/processors/default/renderer/donation.py diff --git a/pytchat/core/pytchat.py b/pytchat/core/pytchat.py index 93605e9..3168f55 100644 --- a/pytchat/core/pytchat.py +++ b/pytchat/core/pytchat.py @@ -29,9 +29,13 @@ class PytchatCore: processor : ChatProcessor + client : httpx.Client + The client for connecting youtube. + You can specify any customized httpx client (e.g. coolies, user agent). + interruptable : bool Allows keyboard interrupts. - Set this parameter to False if your own threading program causes + Set this parameter to False if your own multi-threading program causes the problem. force_replay : bool @@ -57,6 +61,7 @@ class PytchatCore: def __init__(self, video_id, seektime=-1, processor=DefaultProcessor(), + client = httpx.Client(http2=True), interruptable=True, force_replay=False, topchat_only=False, @@ -64,6 +69,7 @@ def __init__(self, video_id, logger=config.logger(__name__), replay_continuation=None ): + self._client = client self._video_id = util.extract_video_id(video_id) self.seektime = seektime if isinstance(processor, tuple): @@ -97,7 +103,7 @@ def _setup(self): """ self.continuation = liveparam.getparam( self._video_id, - channel_id=util.get_channelid(httpx.Client(http2=True), self._video_id), + channel_id=util.get_channelid(self._client, self._video_id), past_sec=3) def _get_chat_component(self): @@ -110,19 +116,18 @@ def _get_chat_component(self): parameter for next chat data ''' try: - with httpx.Client(http2=True) as client: - if self.continuation and self._is_alive: - contents = self._get_contents(self.continuation, client, headers) - metadata, chatdata = self._parser.parse(contents) - timeout = metadata['timeoutMs'] / 1000 - chat_component = { - "video_id": self._video_id, - "timeout": timeout, - "chatdata": chatdata - } - self.continuation = metadata.get('continuation') - self._last_offset_ms = metadata.get('last_offset_ms', 0) - return chat_component + if self.continuation and self._is_alive: + contents = self._get_contents(self.continuation, self._client, headers) + metadata, chatdata = self._parser.parse(contents) + timeout = metadata['timeoutMs'] / 1000 + chat_component = { + "video_id": self._video_id, + "timeout": timeout, + "chatdata": chatdata + } + self.continuation = metadata.get('continuation') + self._last_offset_ms = metadata.get('last_offset_ms', 0) + return chat_component except exceptions.ChatParseException as e: self._logger.debug(f"[{self._video_id}]{str(e)}") self._raise_exception(e) @@ -139,9 +144,8 @@ def _get_contents(self, continuation, client, headers): ------- 'continuationContents' which includes metadata & chat data. ''' - livechat_json = ( - self._get_livechat_json(continuation, client, replay=self._is_replay, offset_ms=self._last_offset_ms) - ) + livechat_json = self._get_livechat_json( + continuation, client, replay=self._is_replay, offset_ms=self._last_offset_ms) contents, dat = self._parser.get_contents(livechat_json) if self._dat == '' and dat: self._dat = dat @@ -152,7 +156,8 @@ def _get_contents(self, continuation, client, headers): self._fetch_url = config._smr continuation = arcparam.getparam( self._video_id, self.seektime, self._topchat_only, util.get_channelid(client, self._video_id)) - livechat_json = self._get_livechat_json(continuation, client, replay=True, offset_ms=self.seektime * 1000) + livechat_json = self._get_livechat_json( + continuation, client, replay=True, offset_ms=self.seektime * 1000) reload_continuation = self._parser.reload_continuation( self._parser.get_contents(livechat_json)[0]) if reload_continuation: @@ -173,15 +178,14 @@ def _get_livechat_json(self, continuation, client, replay: bool, offset_ms: int offset_ms = 0 param = util.get_param(continuation, dat=self._dat, replay=replay, offsetms=offset_ms) for _ in range(MAX_RETRY + 1): - with httpx.Client(http2=True) as client: - try: - response = client.post(self._fetch_url, json=param) - livechat_json = json.loads(response.text) - break - except (json.JSONDecodeError, httpx.ConnectTimeout, httpx.ReadTimeout, httpx.ConnectError) as e: - err = e - time.sleep(2) - continue + try: + response = client.post(self._fetch_url, json=param) + livechat_json = response.json() + break + except (json.JSONDecodeError, httpx.ConnectTimeout, httpx.ReadTimeout, httpx.ConnectError) as e: + err = e + time.sleep(2) + continue else: self._logger.error(f"[{self._video_id}]" f"Exceeded retry count. Last error: {str(err)}") @@ -202,6 +206,8 @@ def is_alive(self): return self._is_alive def terminate(self): + if not self.is_alive(): + return self._is_alive = False self.processor.finalize() diff --git a/pytchat/core_async/livechat.py b/pytchat/core_async/livechat.py index 655f43c..7351470 100644 --- a/pytchat/core_async/livechat.py +++ b/pytchat/core_async/livechat.py @@ -78,6 +78,7 @@ def __init__(self, video_id, seektime=-1, processor=DefaultProcessor(), buffer=None, + client = httpx.AsyncClient(http2=True), interruptable=True, callback=None, done_callback=None, @@ -88,6 +89,7 @@ def __init__(self, video_id, logger=config.logger(__name__), replay_continuation=None ): + self._client:httpx.AsyncClient = client self._video_id = util.extract_video_id(video_id) self.seektime = seektime if isinstance(processor, tuple): @@ -152,9 +154,10 @@ async def _startlisten(self): create and start _listen loop. """ if not self.continuation: + channel_id = await util.get_channelid_async(self._client, self._video_id) self.continuation = liveparam.getparam( self._video_id, - channel_id=util.get_channelid(httpx.Client(http2=True), self._video_id), + channel_id, past_sec=3) await self._listen(self.continuation) @@ -169,10 +172,10 @@ async def _listen(self, continuation): parameter for next chat data ''' try: - async with httpx.AsyncClient(http2=True) as client: + async with self._client as client: while(continuation and self._is_alive): continuation = await self._check_pause(continuation) - contents = await self._get_contents(continuation, client, headers) + contents = await self._get_contents(continuation, client, headers) #Q# metadata, chatdata = self._parser.parse(contents) continuation = metadata.get('continuation') if continuation: @@ -214,9 +217,10 @@ async def _check_pause(self, continuation): ''' self._pauser.put_nowait(None) if not self._is_replay: - async with httpx.AsyncClient(http2=True) as client: - continuation = await liveparam.getparam(self._video_id, - channel_id=util.get_channelid_async(client, self.video_id), + async with self._client as client: + channel_id = await util.get_channelid_async(client, self.video_id) + continuation = liveparam.getparam(self._video_id, + channel_id, past_sec=3) return continuation @@ -338,12 +342,14 @@ def _finish(self, sender): self._logger.debug(f'[{self._video_id}] cancelled:{sender}') def terminate(self): + if not self.is_alive(): + return if self._pauser.empty(): self._pauser.put_nowait(None) self._is_alive = False self._buffer.put_nowait({}) self.processor.finalize() - + def _keyboard_interrupt(self): self.exception = exceptions.ChatDataFinished() self.terminate() diff --git a/pytchat/core_multithread/livechat.py b/pytchat/core_multithread/livechat.py index 153dce1..534d0e3 100644 --- a/pytchat/core_multithread/livechat.py +++ b/pytchat/core_multithread/livechat.py @@ -78,6 +78,7 @@ class LiveChat: def __init__(self, video_id, seektime=-1, processor=DefaultProcessor(), + client = httpx.Client(http2=True), buffer=None, interruptable=True, callback=None, @@ -88,6 +89,7 @@ def __init__(self, video_id, logger=config.logger(__name__), replay_continuation=None ): + self._client = client self._video_id = util.extract_video_id(video_id) self.seektime = seektime if isinstance(processor, tuple): @@ -150,7 +152,7 @@ def _startlisten(self): if not self.continuation: self.continuation = liveparam.getparam( self._video_id, - channel_id=util.get_channelid(httpx.Client(http2=True), self._video_id), + channel_id=util.get_channelid(self._client, self._video_id), past_sec=3) self._listen(self.continuation) @@ -164,7 +166,7 @@ def _listen(self, continuation): parameter for next chat data ''' try: - with httpx.Client(http2=True) as client: + with self._client as client: while(continuation and self._is_alive): continuation = self._check_pause(continuation) contents = self._get_contents(continuation, client, headers) @@ -224,7 +226,8 @@ def _get_contents(self, continuation, client, headers): ------- 'continuationContents' which includes metadata & chat data. ''' - livechat_json = self._get_livechat_json(continuation, client, replay=self._is_replay, offset_ms=self._last_offset_ms) + livechat_json = self._get_livechat_json( + continuation, client, replay=self._is_replay, offset_ms=self._last_offset_ms) contents, dat = self._parser.get_contents(livechat_json) if self._dat == '' and dat: self._dat = dat @@ -235,8 +238,8 @@ def _get_contents(self, continuation, client, headers): self._fetch_url = config._smr continuation = arcparam.getparam( self._video_id, self.seektime, self._topchat_only, util.get_channelid(client, self._video_id)) - livechat_json = (self._get_livechat_json( - continuation, client, replay=True, offset_ms=self.seektime * 1000)) + livechat_json = self._get_livechat_json( + continuation, client, replay=True, offset_ms=self.seektime * 1000) reload_continuation = self._parser.reload_continuation( self._parser.get_contents(livechat_json)[0]) if reload_continuation: @@ -331,6 +334,8 @@ def _finish(self, sender): self._logger.debug(f'[{self._video_id}] cancelled:{sender}') def terminate(self): + if not self.is_alive(): + return if self._pauser.empty(): self._pauser.put_nowait(None) self._is_alive = False diff --git a/pytchat/processors/default/processor.py b/pytchat/processors/default/processor.py index e28da0e..2121a35 100644 --- a/pytchat/processors/default/processor.py +++ b/pytchat/processors/default/processor.py @@ -7,6 +7,7 @@ from .renderer.paidsticker import LiveChatPaidStickerRenderer from .renderer.legacypaid import LiveChatLegacyPaidMessageRenderer from .renderer.membership import LiveChatMembershipItemRenderer +from .renderer.donation import LiveChatDonationAnnouncementRenderer from .. chat_processor import ChatProcessor from ... import config @@ -124,7 +125,8 @@ def __init__(self): "liveChatPaidMessageRenderer": LiveChatPaidMessageRenderer(), "liveChatPaidStickerRenderer": LiveChatPaidStickerRenderer(), "liveChatLegacyPaidMessageRenderer": LiveChatLegacyPaidMessageRenderer(), - "liveChatMembershipItemRenderer": LiveChatMembershipItemRenderer() + "liveChatMembershipItemRenderer": LiveChatMembershipItemRenderer(), + "liveChatDonationAnnouncementRenderer": LiveChatDonationAnnouncementRenderer(), } def process(self, chat_components: list): diff --git a/pytchat/processors/default/renderer/donation.py b/pytchat/processors/default/renderer/donation.py new file mode 100644 index 0000000..7f654e5 --- /dev/null +++ b/pytchat/processors/default/renderer/donation.py @@ -0,0 +1,6 @@ +from .base import BaseRenderer + + +class LiveChatDonationAnnouncementRenderer(BaseRenderer): + def settype(self): + self.chat.type = "donation" \ No newline at end of file diff --git a/pytchat/processors/speed/calculator.py b/pytchat/processors/speed/calculator.py index 52d57df..3bef2ba 100644 --- a/pytchat/processors/speed/calculator.py +++ b/pytchat/processors/speed/calculator.py @@ -82,16 +82,17 @@ def item_count(self): class SpeedCalculator(ChatProcessor, RingQueue): """ - チャットの勢いを計算する。 + Calculate the momentum of the chat. - 一定期間のチャットデータのうち、最初のチャットの投稿時刻と - 最後のチャットの投稿時刻の差を、チャット数で割り返し - 1分あたりの速度に換算する。 + Divide the difference between the time of the first chat and + the time of the last chat in the chat data over a period of + time by the number of chats and convert it to speed per minute. Parameter ---------- capacity : int - RingQueueに格納するチャット勢い算出用データの最大数 + Maximum number of data for calculating chat momentum + to be stored in RingQueue. """ def __init__(self, capacity=10): @@ -111,17 +112,17 @@ def process(self, chat_components: list): def _calc_speed(self): """ - RingQueue内のチャット勢い算出用データリストを元に、 - チャット速度を計算して返す + Calculates the chat speed based on the data list for calculating + the chat momentum in RingQueue. Return --------------------------- - チャット速度(1分間で換算したチャット数) + Chat speed (number of chats converted per minute) """ try: - # キュー内の総チャット数 + # Total number of chats in the queue total = sum(item['chat_count'] for item in self.items) - # キュー内の最初と最後のチャットの時間差 + # Interval between the first and last chats in the queue duration = (self.items[self.last_pos]['endtime'] - self.items[self.first_pos]['starttime']) if duration != 0: return int(total * 60 / duration) @@ -131,19 +132,12 @@ def _calc_speed(self): def _put_chatdata(self, actions): """ - チャットデータからタイムスタンプを読み取り、勢い測定用のデータを組み立て、 - RingQueueに投入する。 - 200円以上のスパチャはtickerとmessageの2つのデータが生成されるが、 - tickerの方は時刻データの場所が異なることを利用し、勢いの集計から除外している。 Parameter --------- actions : List[dict] - チャットデータ(addChatItemAction) のリスト + List of addChatItemActions """ def _put_emptydata(): - ''' - チャットデータがない場合に空のデータをキューに投入する。 - ''' timestamp_now = int(time.time()) self.put({ 'chat_count': 0, @@ -152,9 +146,6 @@ def _put_emptydata(): }) def _get_timestamp(action: dict): - """ - チャットデータから時刻データを取り出す。 - """ try: item = action['addChatItemAction']['item'] timestamp = int(item[list(item.keys())[0]]['timestampUsec']) @@ -166,32 +157,24 @@ def _get_timestamp(action: dict): _put_emptydata() return - # actions内の時刻データを持つチャットデータの数 counter = 0 - # actions内の最初のチャットデータの時刻 starttime = None - # actions内の最後のチャットデータの時刻 endtime = None for action in actions: - # チャットデータからtimestampUsecを読み取る + # Get timestampUsec from chatdata gettime = _get_timestamp(action) - # 時刻のないデータだった場合は次の行のデータで読み取り試行 if gettime is None: continue - # 最初に有効な時刻を持つデータのtimestampをstarttimeに設定 if starttime is None: starttime = gettime - # 最後のtimestampを設定(途中で時刻のないデータの場合もあるので上書きしていく) endtime = gettime - # チャットの数をインクリメント counter += 1 - # チャット速度用のデータをRingQueueに送る if starttime is None or endtime is None: _put_emptydata() return From c9c235061cad6844e972bbe79b749606658bd34d Mon Sep 17 00:00:00 2001 From: taizan-hokouto <55448286+taizan-hokuto@users.noreply.github.com> Date: Sat, 24 Jul 2021 22:13:18 +0900 Subject: [PATCH 2/6] Add tests --- tests/test_calculator_get_item.py | 140 ---------------------------- tests/test_calculator_parse.py | 1 - tests/test_compatible_processor2.py | 24 +++++ tests/test_default_processor2.py | 94 +++++++++++++++++++ tests/test_speed_calculator2.py | 16 ++++ 5 files changed, 134 insertions(+), 141 deletions(-) delete mode 100644 tests/test_calculator_get_item.py create mode 100644 tests/test_compatible_processor2.py create mode 100644 tests/test_default_processor2.py create mode 100644 tests/test_speed_calculator2.py diff --git a/tests/test_calculator_get_item.py b/tests/test_calculator_get_item.py deleted file mode 100644 index afc48d0..0000000 --- a/tests/test_calculator_get_item.py +++ /dev/null @@ -1,140 +0,0 @@ -from pytchat.processors.superchat.calculator import SuperchatCalculator - -get_item = SuperchatCalculator()._get_item - -dict_test = { - 'root':{ - 'node0' : 'value0', - 'node1' : 'value1', - 'node2' : { - 'node2-0' : 'value2-0' - }, - - 'node3' : [ - {'node3-0' : 'value3-0'}, - {'node3-1' : - {'node3-1-0' : 'value3-1-0'} - } - ], - 'node4' : [], - 'node5' : [ - [ - {'node5-1-0' : 'value5-1-0'}, - {'node5-1-1' : 'value5-1-1'}, - ], - {'node5-0' : 'value5-0'}, - - ] - } -} - -items_test0 = [ - 'root', - 'node1' -] - - -items_test_not_found0 = [ - 'root', - 'other_data' -] - - -items_test_nest = [ - 'root', - 'node2', - 'node2-0' -] - -items_test_list0 = [ - 'root', - 'node3', - 1, - 'node3-1' -] - -items_test_list1 = [ - 'root', - 'node3', - 1, - 'node3-1', - 'node3-1-0' -] - -items_test_list2 = [ - 'root', - 'node4', - None -] - -items_test_list3 = [ - 'root', - 'node4' -] - -items_test_list_nest = [ - 'root', - 'node5', - 0, - 1, - 'node5-1-1' -] - -items_test_list_nest_not_found1 = [ - 'root', - 'node5', - 0, - 1, - 'node5-1-1', - 'nodez' -] - -items_test_not_found1 = [ - 'root', - 'node3', - 2, - 'node3-1', - 'node3-1-0' -] - -items_test_not_found2 = [ - 'root', - 'node3', - 2, - 'node3-1', - 'node3-1-0', - 'nodex' -] -def test_get_items_0(): - assert get_item(dict_test, items_test0) == 'value1' - -def test_get_items_1(): - assert get_item(dict_test, items_test_not_found0) is None - -def test_get_items_2(): - assert get_item(dict_test, items_test_nest) == 'value2-0' - -def test_get_items_3(): - assert get_item( - dict_test, items_test_list0) == {'node3-1-0' : 'value3-1-0'} - -def test_get_items_4(): - assert get_item(dict_test, items_test_list1) == 'value3-1-0' - -def test_get_items_5(): - assert get_item(dict_test, items_test_not_found1) == None - -def test_get_items_6(): - assert get_item(dict_test, items_test_not_found2) == None - -def test_get_items_7(): - assert get_item(dict_test, items_test_list2) == None - -def test_get_items_8(): - assert get_item(dict_test, items_test_list_nest) == 'value5-1-1' - -def test_get_items_9(): - assert get_item(dict_test, items_test_list_nest_not_found1) == None - -def test_get_items_10(): - assert get_item(dict_test, items_test_list3) == [] diff --git a/tests/test_calculator_parse.py b/tests/test_calculator_parse.py index 73d7955..592dec4 100644 --- a/tests/test_calculator_parse.py +++ b/tests/test_calculator_parse.py @@ -67,6 +67,5 @@ def test_process_2(): 'chatdata': load_chatdata(r"tests/testdata/calculator/replay_end.json") } assert False - SuperchatCalculator().process([chat_component]) except ChatParseException: assert True diff --git a/tests/test_compatible_processor2.py b/tests/test_compatible_processor2.py new file mode 100644 index 0000000..50a5301 --- /dev/null +++ b/tests/test_compatible_processor2.py @@ -0,0 +1,24 @@ +import pytchat +from pytchat.processors.compatible.processor import CompatibleProcessor + + +root_keys = ('kind', 'etag', 'nextPageToken', 'pollingIntervalMillis', 'pageInfo', 'items') +item_keys = ('kind', 'etag', 'id', 'snippet', 'authorDetails') +snippet_keys = ('type', 'liveChatId', 'authorChannelId', 'publishedAt', 'hasDisplayContent', 'displayMessage', 'textMessageDetails') +author_details_keys = ('channelId', 'channelUrl', 'displayName', 'profileImageUrl', 'isVerified', 'isChatOwner', 'isChatSponsor', 'isChatModerator') + +def test_compatible_processor(): + stream = pytchat.create("Hj-wnLIYKjw", seektime = 6000, processor=CompatibleProcessor()) + while stream.is_alive(): + chat = stream.get() + for key in chat.keys(): + assert key in root_keys + for key in chat["items"][0].keys(): + assert key in item_keys + for key in chat["items"][0]["snippet"].keys(): + assert key in snippet_keys + for key in chat["items"][0]["authorDetails"].keys(): + assert key in author_details_keys + break + + \ No newline at end of file diff --git a/tests/test_default_processor2.py b/tests/test_default_processor2.py new file mode 100644 index 0000000..5f415c5 --- /dev/null +++ b/tests/test_default_processor2.py @@ -0,0 +1,94 @@ +import asyncio +import pytchat +from concurrent.futures import CancelledError +from pytchat.core_multithread.livechat import LiveChat +from pytchat.core_async.livechat import LiveChatAsync + +cases = [ + { + "video_id":"1X7oL0hDnMg", "seektime":1620, + "result1":{'textMessage': 84}, + "result2":{'': 83, 'MODERATOR': 1} + }, + { + "video_id":"Hj-wnLIYKjw", "seektime":420, + "result1":{'superChat': 1, 'newSponsor': 6, 'textMessage': 63, 'donation': 1}, + "result2":{'': 59, 'MEMBER': 12} + }, + { + "video_id":"S8dmq5YIUoc", "seektime":3, + "result1":{'textMessage': 86}, + "result2":{'': 62, 'MEMBER': 21, 'OWNER': 2, 'VERIFIED': 1} + },{ + "video_id":"yLrstz80MKs", "seektime":30, + "result1":{'superSticker': 8, 'superChat': 2, 'textMessage': 67}, + "result2":{'': 73, 'MEMBER': 4} + } +] + +def test_archived_stream(): + for case in cases: + stream = pytchat.create(video_id=case["video_id"], seektime=case["seektime"]) + while stream.is_alive(): + chat = stream.get() + agg1 = {} + agg2 = {} + for c in chat.items: + if c.type in agg1: + agg1[c.type] += 1 + else: + agg1[c.type] = 1 + if c.author.type in agg2: + agg2[c.author.type] += 1 + else: + agg2[c.author.type] = 1 + break + assert agg1 == case["result1"] + assert agg2 == case["result2"] + + +def test_archived_stream_multithread(): + for case in cases: + stream = LiveChat(video_id=case["video_id"], seektime=case["seektime"]) + while stream.is_alive(): + chat = stream.get() + agg1 = {} + agg2 = {} + for c in chat.items: + if c.type in agg1: + agg1[c.type] += 1 + else: + agg1[c.type] = 1 + if c.author.type in agg2: + agg2[c.author.type] += 1 + else: + agg2[c.author.type] = 1 + break + assert agg1 == case["result1"] + assert agg2 == case["result2"] + +def test_async_live_stream(): + async def test_loop(): + for case in cases: + stream = LiveChatAsync(video_id=case["video_id"], seektime=case["seektime"]) + while stream.is_alive(): + chat = await stream.get() + agg1 = {} + agg2 = {} + for c in chat.items: + if c.type in agg1: + agg1[c.type] += 1 + else: + agg1[c.type] = 1 + if c.author.type in agg2: + agg2[c.author.type] += 1 + else: + agg2[c.author.type] = 1 + break + assert agg1 == case["result1"] + assert agg2 == case["result2"] + loop = asyncio.get_event_loop() + try: + loop.run_until_complete(test_loop()) + except CancelledError: + assert True diff --git a/tests/test_speed_calculator2.py b/tests/test_speed_calculator2.py new file mode 100644 index 0000000..dee85f0 --- /dev/null +++ b/tests/test_speed_calculator2.py @@ -0,0 +1,16 @@ +import json +import pytchat +from pytchat.parser.live import Parser +from pytchat.processors.speed.calculator import SpeedCalculator + +parser = Parser(is_replay=False) + + +def test_speed_1(): + stream = pytchat.create("Hj-wnLIYKjw", seektime = 6000,processor=SpeedCalculator()) + while stream.is_alive(): + speed = stream.get() + assert speed > 100 + break +test_speed_1() + \ No newline at end of file From 8949599232a306b44f64eafecaef930965227cf8 Mon Sep 17 00:00:00 2001 From: taizan-hokouto <55448286+taizan-hokuto@users.noreply.github.com> Date: Sat, 24 Jul 2021 22:13:39 +0900 Subject: [PATCH 3/6] Update pipfile --- Pipfile | 2 +- Pipfile.lock | 262 ++++++++++++++++++++++----------------------------- 2 files changed, 113 insertions(+), 151 deletions(-) diff --git a/Pipfile b/Pipfile index 7d6eada..fa1f7bf 100644 --- a/Pipfile +++ b/Pipfile @@ -4,7 +4,7 @@ verify_ssl = true name = "pypi" [packages] -httpx = {extras = ["http2"], version = "0.16.1"} +httpx = {extras = ["http2"]} [dev-packages] pytest-mock = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 48936d2..2845d50 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "e1eb34f14c75998519a90838b283ccd23bd168afa8e4837f956c5c4df66376f9" + "sha256": "74b83f2e50bc16f8d90c06ddc775d24ee427f8481a2501f62170bf5b76a2f1bd" }, "pipfile-spec": 6, "requires": {}, @@ -14,6 +14,14 @@ ] }, "default": { + "anyio": { + "hashes": [ + "sha256:929a6852074397afe1d989002aa96d457e3e1e5441357c60d03e7eea0e65e1b0", + "sha256:ae57a67583e5ff8b4af47666ff5651c3732d45fd26c929253748e796af860374" + ], + "markers": "python_full_version >= '3.6.2'", + "version": "==3.3.0" + }, "certifi": { "hashes": [ "sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee", @@ -26,6 +34,7 @@ "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6", "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042" ], + "markers": "python_version >= '3.6'", "version": "==0.12.0" }, "h2": { @@ -44,21 +53,22 @@ }, "httpcore": { "hashes": [ - "sha256:37ae835fb370049b2030c3290e12ed298bf1473c41bb72ca4aa78681eba9b7c9", - "sha256:93e822cd16c32016b414b789aeff4e855d0ccbfc51df563ee34d4dbadbb3bcdc" + "sha256:b0d16f0012ec88d8cc848f5a55f8a03158405f4bca02ee49bc4ca2c1fda49f3e", + "sha256:db4c0dcb8323494d01b8c6d812d80091a31e520033e7b0120883d6f52da649ff" ], - "version": "==0.12.3" + "markers": "python_version >= '3.6'", + "version": "==0.13.6" }, "httpx": { "extras": [ "http2" ], "hashes": [ - "sha256:126424c279c842738805974687e0518a94c7ae8d140cd65b9c4f77ac46ffa537", - "sha256:9cffb8ba31fac6536f2c8cde30df859013f59e4bcc5b8d43901cb3654a8e0a5b" + "sha256:979afafecb7d22a1d10340bafb403cf2cb75aff214426ff206521fc79d26408c", + "sha256:9f99c15d33642d38bce8405df088c1c4cfd940284b4290cacbfb02e64f4877c6" ], "index": "pypi", - "version": "==0.16.1" + "version": "==0.18.2" }, "hyperframe": { "hashes": [ @@ -89,23 +99,42 @@ "sha256:471b71698eac1c2112a40ce2752bb2f4a4814c22a54a3eed3676bc0f5ca9f663", "sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de" ], + "markers": "python_version >= '3.5'", "version": "==1.2.0" } }, "develop": { + "anyio": { + "hashes": [ + "sha256:929a6852074397afe1d989002aa96d457e3e1e5441357c60d03e7eea0e65e1b0", + "sha256:ae57a67583e5ff8b4af47666ff5651c3732d45fd26c929253748e796af860374" + ], + "markers": "python_full_version >= '3.6.2'", + "version": "==3.3.0" + }, + "atomicwrites": { + "hashes": [ + "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197", + "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a" + ], + "markers": "sys_platform == 'win32'", + "version": "==1.4.0" + }, "attrs": { "hashes": [ "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1", "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==21.2.0" }, "bleach": { "hashes": [ - "sha256:6123ddc1052673e52bab52cdc955bcb57a015264a1c57d37bea2f6b817af0125", - "sha256:98b3170739e5e83dd9dc19633f074727ad848cbedb6026708c8ac2d3b697a433" + "sha256:306483a5a9795474160ad57fce3ddd1b50551e981eed8e15a582d34cef28aafa", + "sha256:ae976d7174bba988c0b632def82fdc94235756edfb14e6558a9c5be555c9fb78" ], - "version": "==3.3.0" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==3.3.1" }, "certifi": { "hashes": [ @@ -114,96 +143,28 @@ ], "version": "==2021.5.30" }, - "cffi": { - "hashes": [ - "sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813", - "sha256:04c468b622ed31d408fea2346bec5bbffba2cc44226302a0de1ade9f5ea3d373", - "sha256:06d7cd1abac2ffd92e65c0609661866709b4b2d82dd15f611e602b9b188b0b69", - "sha256:06db6321b7a68b2bd6df96d08a5adadc1fa0e8f419226e25b2a5fbf6ccc7350f", - "sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06", - "sha256:0f861a89e0043afec2a51fd177a567005847973be86f709bbb044d7f42fc4e05", - "sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea", - "sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee", - "sha256:1bf1ac1984eaa7675ca8d5745a8cb87ef7abecb5592178406e55858d411eadc0", - "sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396", - "sha256:24a570cd11895b60829e941f2613a4f79df1a27344cbbb82164ef2e0116f09c7", - "sha256:24ec4ff2c5c0c8f9c6b87d5bb53555bf267e1e6f70e52e5a9740d32861d36b6f", - "sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73", - "sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315", - "sha256:293e7ea41280cb28c6fcaaa0b1aa1f533b8ce060b9e701d78511e1e6c4a1de76", - "sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1", - "sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49", - "sha256:3c3f39fa737542161d8b0d680df2ec249334cd70a8f420f71c9304bd83c3cbed", - "sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892", - "sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482", - "sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058", - "sha256:51182f8927c5af975fece87b1b369f722c570fe169f9880764b1ee3bca8347b5", - "sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53", - "sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045", - "sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3", - "sha256:681d07b0d1e3c462dd15585ef5e33cb021321588bebd910124ef4f4fb71aef55", - "sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5", - "sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e", - "sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c", - "sha256:72d8d3ef52c208ee1c7b2e341f7d71c6fd3157138abf1a95166e6165dd5d4369", - "sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827", - "sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053", - "sha256:99cd03ae7988a93dd00bcd9d0b75e1f6c426063d6f03d2f90b89e29b25b82dfa", - "sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4", - "sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322", - "sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132", - "sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62", - "sha256:a465da611f6fa124963b91bf432d960a555563efe4ed1cc403ba5077b15370aa", - "sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0", - "sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396", - "sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e", - "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991", - "sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6", - "sha256:cc5a8e069b9ebfa22e26d0e6b97d6f9781302fe7f4f2b8776c3e1daea35f1adc", - "sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1", - "sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406", - "sha256:df5052c5d867c1ea0b311fb7c3cd28b19df469c056f7fdcfe88c7473aa63e333", - "sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d", - "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c" - ], - "version": "==1.14.5" - }, - "chardet": { - "hashes": [ - "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa", - "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5" - ], - "version": "==4.0.0" + "charset-normalizer": { + "hashes": [ + "sha256:88fce3fa5b1a84fdcb3f603d889f723d1dd89b26059d0123ca435570e848d5e1", + "sha256:c46c3ace2d744cfbdebceaa3c19ae691f53ae621b39fd7570f59d14fb7f2fd12" + ], + "markers": "python_version >= '3'", + "version": "==2.0.3" }, "colorama": { "hashes": [ "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b", "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2" ], + "markers": "platform_system == 'Windows' and sys_platform == 'win32'", "version": "==0.4.4" }, - "cryptography": { - "hashes": [ - "sha256:0f1212a66329c80d68aeeb39b8a16d54ef57071bf22ff4e521657b27372e327d", - "sha256:1e056c28420c072c5e3cb36e2b23ee55e260cb04eee08f702e0edfec3fb51959", - "sha256:240f5c21aef0b73f40bb9f78d2caff73186700bf1bc6b94285699aff98cc16c6", - "sha256:26965837447f9c82f1855e0bc8bc4fb910240b6e0d16a664bb722df3b5b06873", - "sha256:37340614f8a5d2fb9aeea67fd159bfe4f5f4ed535b1090ce8ec428b2f15a11f2", - "sha256:3d10de8116d25649631977cb37da6cbdd2d6fa0e0281d014a5b7d337255ca713", - "sha256:3d8427734c781ea5f1b41d6589c293089704d4759e34597dce91014ac125aad1", - "sha256:7ec5d3b029f5fa2b179325908b9cd93db28ab7b85bb6c1db56b10e0b54235177", - "sha256:8e56e16617872b0957d1c9742a3f94b43533447fd78321514abbe7db216aa250", - "sha256:de4e5f7f68220d92b7637fc99847475b59154b7a1b3868fb7385337af54ac9ca", - "sha256:eb8cc2afe8b05acbd84a43905832ec78e7b3873fb124ca190f574dca7389a87d", - "sha256:ee77aa129f481be46f8d92a1a7db57269a2f23052d5f2433b4621bb457081cc9" - ], - "version": "==3.4.7" - }, "docutils": { "hashes": [ "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125", "sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==0.17.1" }, "h11": { @@ -211,25 +172,27 @@ "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6", "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042" ], + "markers": "python_version >= '3.6'", "version": "==0.12.0" }, "httpcore": { "hashes": [ - "sha256:37ae835fb370049b2030c3290e12ed298bf1473c41bb72ca4aa78681eba9b7c9", - "sha256:93e822cd16c32016b414b789aeff4e855d0ccbfc51df563ee34d4dbadbb3bcdc" + "sha256:b0d16f0012ec88d8cc848f5a55f8a03158405f4bca02ee49bc4ca2c1fda49f3e", + "sha256:db4c0dcb8323494d01b8c6d812d80091a31e520033e7b0120883d6f52da649ff" ], - "version": "==0.12.3" + "markers": "python_version >= '3.6'", + "version": "==0.13.6" }, "httpx": { "extras": [ "http2" ], "hashes": [ - "sha256:126424c279c842738805974687e0518a94c7ae8d140cd65b9c4f77ac46ffa537", - "sha256:9cffb8ba31fac6536f2c8cde30df859013f59e4bcc5b8d43901cb3654a8e0a5b" + "sha256:979afafecb7d22a1d10340bafb403cf2cb75aff214426ff206521fc79d26408c", + "sha256:9f99c15d33642d38bce8405df088c1c4cfd940284b4290cacbfb02e64f4877c6" ], "index": "pypi", - "version": "==0.16.1" + "version": "==0.18.2" }, "idna": { "hashes": [ @@ -240,10 +203,11 @@ }, "importlib-metadata": { "hashes": [ - "sha256:960d52ba7c21377c990412aca380bf3642d734c2eaab78a2c39319f67c6a5786", - "sha256:e592faad8de1bda9fe920cf41e15261e7131bcf266c30306eec00e8e225c1dd5" + "sha256:079ada16b7fc30dfbb5d13399a5113110dab1aa7c2bc62f66af75f0b717c8cac", + "sha256:9f55f560e116f8643ecf2922d9cd3e1c7e8d52e683178fecd9d08f6aa357e11e" ], - "version": "==4.4.0" + "markers": "python_version >= '3.6'", + "version": "==4.6.1" }, "iniconfig": { "hashes": [ @@ -252,40 +216,35 @@ ], "version": "==1.1.1" }, - "jeepney": { - "hashes": [ - "sha256:7d59b6622675ca9e993a6bd38de845051d315f8b0c72cca3aef733a20b648657", - "sha256:aec56c0eb1691a841795111e184e13cad504f7703b9a64f63020816afa79a8ae" - ], - "markers": "sys_platform == 'linux'", - "version": "==0.6.0" - }, "keyring": { "hashes": [ "sha256:045703609dd3fccfcdb27da201684278823b72af515aedec1a8515719a038cb8", "sha256:8f607d7d1cc502c43a932a275a56fe47db50271904513a379d39df1af277ac48" ], + "markers": "python_version >= '3.6'", "version": "==23.0.1" }, "packaging": { "hashes": [ - "sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5", - "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a" + "sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7", + "sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14" ], - "version": "==20.9" + "markers": "python_version >= '3.6'", + "version": "==21.0" }, "pkginfo": { "hashes": [ - "sha256:029a70cb45c6171c329dfc890cde0879f8c52d6f3922794796e06f577bb03db4", - "sha256:9fdbea6495622e022cc72c2e5e1b735218e4ffb2a2a69cde2694a6c1f16afb75" + "sha256:37ecd857b47e5f55949c41ed061eb51a0bee97a87c969219d144c0e023982779", + "sha256:e7432f81d08adec7297633191bbf0bd47faf13cd8724c3a13250e51d542635bd" ], - "version": "==1.7.0" + "version": "==1.7.1" }, "pluggy": { "hashes": [ "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0", "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==0.13.1" }, "py": { @@ -293,20 +252,15 @@ "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3", "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.10.0" }, - "pycparser": { - "hashes": [ - "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0", - "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705" - ], - "version": "==2.20" - }, "pygments": { "hashes": [ "sha256:a18f47b506a429f6f4b9df81bb02beab9ca21d0a5fee38ed15aef65f0545519f", "sha256:d66e804411278594d764fc69ec36ec13d9ae9147193a1740cd34d272ca383b8e" ], + "markers": "python_version >= '3.5'", "version": "==2.9.0" }, "pyparsing": { @@ -314,6 +268,7 @@ "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.4.7" }, "pytest": { @@ -321,23 +276,32 @@ "sha256:50bcad0a0b9c5a72c8e4e7c9855a3ad496ca6a881a3641b4260605450772c54b", "sha256:91ef2131a9bd6be8f76f1f08eac5c5317221d6ad1e143ae03894b862e8976890" ], + "markers": "python_version >= '3.6'", "version": "==6.2.4" }, "pytest-httpx": { "hashes": [ - "sha256:0a7c56e559b23efbf857054cd74de60a7c540694a162423f89c70da6ad358d8e", - "sha256:d32e8f6fb7e028f0313f5f5a2d463c8673eb43fd11a9bfe8527299717a7764c4" + "sha256:1e135b8779060091fa1c87d8aff7904921e8bea95fce5e971a0262764d064b12", + "sha256:e262932f2d3ce380da8273c7bacbcfdc2c94e167fa94da29571caaf1f4d3ba27" ], "index": "pypi", - "version": "==0.10.1" + "version": "==0.12.0" }, "pytest-mock": { "hashes": [ - "sha256:024e405ad382646318c4281948aadf6fe1135632bea9cc67366ea0c4098ef5f2", - "sha256:a4d6d37329e4a893e77d9ffa89e838dd2b45d5dc099984cf03c703ac8411bb82" + "sha256:30c2f2cc9759e76eee674b81ea28c9f0b94f8f0445a1b87762cadf774f0df7e3", + "sha256:40217a058c52a63f1042f0784f62009e976ba824c418cced42e88d5f40ab0e62" ], "index": "pypi", - "version": "==3.3.1" + "version": "==3.6.1" + }, + "pywin32-ctypes": { + "hashes": [ + "sha256:24ffc3b341d457d48e8922352130cf2644024a4ff09762a2261fd34c36ee5942", + "sha256:9dc2d991b3479cc2df15930958b674a48a227d5361d413827a4cfd0b5876fc98" + ], + "markers": "sys_platform == 'win32'", + "version": "==0.2.0" }, "readme-renderer": { "hashes": [ @@ -348,10 +312,11 @@ }, "requests": { "hashes": [ - "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804", - "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e" + "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24", + "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7" ], - "version": "==2.25.1" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==2.26.0" }, "requests-toolbelt": { "hashes": [ @@ -370,19 +335,12 @@ ], "version": "==1.5.0" }, - "secretstorage": { - "hashes": [ - "sha256:422d82c36172d88d6a0ed5afdec956514b189ddbfb72fefab0c8a1cee4eaf71f", - "sha256:fd666c51a6bf200643495a04abb261f83229dcb6fd8472ec393df7ffc8b6f195" - ], - "markers": "sys_platform == 'linux'", - "version": "==3.3.1" - }, "six": { "hashes": [ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.16.0" }, "sniffio": { @@ -390,6 +348,7 @@ "sha256:471b71698eac1c2112a40ce2752bb2f4a4814c22a54a3eed3676bc0f5ca9f663", "sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de" ], + "markers": "python_version >= '3.5'", "version": "==1.2.0" }, "toml": { @@ -397,30 +356,32 @@ "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==0.10.2" }, "tqdm": { "hashes": [ - "sha256:736524215c690621b06fc89d0310a49822d75e599fcd0feb7cc742b98d692493", - "sha256:cd5791b5d7c3f2f1819efc81d36eb719a38e0906a7380365c556779f585ea042" + "sha256:5aa445ea0ad8b16d82b15ab342de6b195a722d75fc1ef9934a46bba6feafbc64", + "sha256:8bb94db0d4468fea27d004a0f1d1c02da3cdedc00fe491c0de986b76a04d6b0a" ], - "version": "==4.61.0" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==4.61.2" }, "twine": { "hashes": [ - "sha256:34352fd52ec3b9d29837e6072d5a2a7c6fe4290e97bba46bb8d478b5c598f7ab", - "sha256:ba9ff477b8d6de0c89dd450e70b2185da190514e91c42cc62f96850025c10472" + "sha256:087328e9bb405e7ce18527a2dca4042a84c7918658f951110b38bc135acab218", + "sha256:4caec0f1ed78dc4c9b83ad537e453d03ce485725f2aea57f1bb3fdde78dae936" ], "index": "pypi", - "version": "==3.2.0" + "version": "==3.4.2" }, "urllib3": { "hashes": [ - "sha256:753a0374df26658f99d826cfe40394a686d05985786d946fbe4165b5148f5a7c", - "sha256:a7acd0977125325f516bda9735fa7142b909a8d01e8b2e4c8108d0984e6e0098" + "sha256:39fb8672126159acb139a7718dd10806104dec1e2f0f6c88aab05d17df10c8d4", + "sha256:f57b4c16c62fa2760b7e3d97c35b255512fb6b59a259730f36ba32ce9f8e342f" ], - "index": "pypi", - "version": "==1.26.5" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", + "version": "==1.26.6" }, "webencodings": { "hashes": [ @@ -431,18 +392,19 @@ }, "wheel": { "hashes": [ - "sha256:906864fb722c0ab5f2f9c35b2c65e3af3c009402c108a709c0aca27bc2c9187b", - "sha256:aaef9b8c36db72f8bf7f1e54f85f875c4d466819940863ca0b3f3f77f0a1646f" + "sha256:78b5b185f0e5763c26ca1e324373aadd49182ca90e825f7853f4b2509215dc0e", + "sha256:e11eefd162658ea59a60a0f6c7d493a7190ea4b9a85e335b33489d9f17e0245e" ], "index": "pypi", - "version": "==0.36.1" + "version": "==0.36.2" }, "zipp": { "hashes": [ - "sha256:3607921face881ba3e026887d8150cca609d517579abe052ac81fc5aeffdbd76", - "sha256:51cb66cc54621609dd593d1787f286ee42a5c0adbb4b29abea5a63edc3e03098" + "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3", + "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4" ], - "version": "==3.4.1" + "markers": "python_version >= '3.6'", + "version": "==3.5.0" } } } From 604c52e608e767e2edbddd6319a539e40a60118d Mon Sep 17 00:00:00 2001 From: taizan-hokouto <55448286+taizan-hokuto@users.noreply.github.com> Date: Sat, 24 Jul 2021 22:13:52 +0900 Subject: [PATCH 4/6] Update requirements --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 07ecc5a..857262a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -httpx[http2]==0.16.1 \ No newline at end of file +httpx[http2] \ No newline at end of file From 76118ba196c89a2220e207f9ee830b71d1a4f75b Mon Sep 17 00:00:00 2001 From: taizan-hokouto <55448286+taizan-hokuto@users.noreply.github.com> Date: Sat, 24 Jul 2021 22:59:26 +0900 Subject: [PATCH 5/6] Update classifiers --- setup.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 07744af..5fe7008 100644 --- a/setup.py +++ b/setup.py @@ -50,8 +50,9 @@ def _test_requirements(): 'Natural Language :: Japanese', 'Development Status :: 4 - Beta', 'Programming Language :: Python', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', 'License :: OSI Approved :: MIT License', ], description="a python library for fetching youtube live chat.", From f511049eaa3c8230f39404533216fb1253493366 Mon Sep 17 00:00:00 2001 From: taizan-hokouto <55448286+taizan-hokuto@users.noreply.github.com> Date: Sat, 24 Jul 2021 22:59:46 +0900 Subject: [PATCH 6/6] Increment version --- pytchat/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pytchat/__init__.py b/pytchat/__init__.py index e36731d..54e5cd2 100644 --- a/pytchat/__init__.py +++ b/pytchat/__init__.py @@ -1,8 +1,8 @@ """ pytchat is a lightweight python library to browse youtube livechat without Selenium or BeautifulSoup. """ -__copyright__ = 'Copyright (C) 2019, 2020 taizan-hokuto' -__version__ = '0.5.4' +__copyright__ = 'Copyright (C) 2019, 2020, 2021 taizan-hokuto' +__version__ = '0.5.5' __license__ = 'MIT' __author__ = 'taizan-hokuto' __author_email__ = '55448286+taizan-hokuto@users.noreply.github.com'