def test_remove(self): Registry.set("foo", "bar", "dummy") FooManager.remove("bar") with self.assertRaises(NotFound) as cm: FooManager.remove("bar") self.assertEqual("No foo matched your argument: bar!", str(cm.exception))
def test_singleton(self): a = Registry() b = Registry() self.assertIs(a, b) a[1] = 2 self.assertEqual({1: 2}, b)
def test_get(self): with self.assertRaises(NotFound) as cm: FooManager.get("bar") self.assertEqual("No foo matched your argument: bar!", str(cm.exception)) Registry.set("foo", "bar", self.data) obj = FooManager.get("bar") self.assertIsInstance(obj, FooManager.model) self.assertDictEqual(self.data, obj.asdict())
def update_quota(cls, cost: int): """ Update current date youtube quota usage according to this guide https://developers.google.com/youtube/v3/determine_quota_cost. :param int cost: """ date = cls.quota_date() quota = Registry.get(cls.quota_key, date, default=0) + cost Registry.set(cls.quota_key, {date: quota})
def set(cls, data: Dict): obj = cls.model(**data) key = getattr(obj, cls.key) with contextlib.suppress(KeyError): data = Registry.get(cls.namespace, key) for field in attr.fields(cls.model): if field.metadata.get("keep") and not getattr(obj, field.name): setattr(obj, field.name, data.get(field.name)) Registry.set(cls.namespace, key, obj.asdict()) return obj
def get_tags(cls, refresh=False) -> List[Tag]: """ Return a list of the most popular last.fm tags. The result will be cached for 30 days. \f :rtype: :class:`list` of :class:`pydrag.Tag` """ cls.assert_config() def retrieve_tags(): page = 1 tags = [] # type: List[dict] with spinner("Fetching tags"): while len(tags) < 1000: tags.extend([ t.to_dict() for t in Tag.get_top_tags(limit=250, page=page) ]) page += 1 return tags return [ Tag(**data) for data in Registry.cache( key="last.fm_tag_list", ttl=timedelta(days=30), func=retrieve_tags, refresh=refresh, ) ]
def test_get_tags(self, get_top_tags, time, assert_config): time.return_value = 1 get_top_tags.side_effect = [ [Tag(name=i) for i in range(0, 250)], [Tag(name=i) for i in range(250, 500)], [Tag(name=i) for i in range(500, 750)], [Tag(name=i) for i in range(750, 1000)], ] names = [t.name for t in LastService.get_tags()] self.assertEqual(list(range(0, 1000)), names) get_top_tags.assert_has_calls( [ mock.call(limit=250, page=1), mock.call(limit=250, page=2), mock.call(limit=250, page=3), mock.call(limit=250, page=4), ] ) tags, ttl = Registry.get("last.fm_tag_list") self.assertEqual(1000, len(tags)) self.assertEqual({"name": 0}, tags[0]) self.assertEqual(timedelta(days=30, seconds=1).total_seconds(), ttl) assert_config.assert_called_once()
def callme(ttl, value, refresh=False): return Registry.cache( key="foo", ttl=timedelta(seconds=ttl), func=lambda: value, refresh=refresh, )
def get(cls, key, **kwargs): with contextlib.suppress(KeyError): data = Registry.get(cls.namespace, str(key), **kwargs) with contextlib.suppress(TypeError): return cls.model(**data) return data raise NotFound("No {} matched your argument: {}!".format( cls.namespace, key))
def test_persist(self): try: Registry.set(1, 2, 3, 4) tmp = tempfile.mkdtemp() file_path = os.path.join(tmp, "foo.json") Registry.persist(file_path) Registry.set(1, 2, 3, 5) Registry._obj = {} Registry.from_file(file_path) self.assertEqual({"1": {"2": {"3": 4}}}, Registry()) finally: shutil.rmtree(tmp)
def test_update(self): foo = FooManager.set(self.data) new_foo = FooManager.update(foo, dict(value=2)) self.assertIsNot(foo, new_foo) self.assertIsInstance(new_foo, FooManager.model) expected = dict(id="a", value=2, keeper="keep") self.assertDictEqual(expected, Registry.get("foo", "a")) self.assertDictEqual(expected, new_foo.asdict())
def cli(ctx: click.Context): """Create and upload music playlists to youtube.""" appdir = click.get_app_dir("pytuber", False) if not os.path.exists(appdir): print("Application Directory not found! Creating one at", appdir) os.makedirs(appdir) cfg = os.path.join(appdir, "storage.db") init_registry(cfg, version) ctx.call_on_close(lambda: Registry.persist(cfg))
def test_set(self): foo = FooManager.set(self.data) self.assertIsInstance(foo, FooManager.model) self.assertDictEqual(self.data, Registry.get("foo", "a")) self.assertDictEqual(self.data, foo.asdict()) bar = FooManager.set(dict(id="a", value=1)) self.assertEqual(foo.asdict(), bar.asdict()) thug = FooManager.set(dict(id="a", value=1, keeper="peek")) self.assertEqual("peek", thug.keeper)
def test_get_user(self, find, time, assert_config): time.return_value = 1 my_user = self.get_user() find.return_value = my_user self.assertEqual(my_user, LastService.get_user("rj")) find.assert_called_once_with("rj") user, ttl = Registry.get("last.fm_user_rj") self.assertEqual(self.get_user().to_dict(), user) self.assertEqual(timedelta(hours=24, seconds=1).total_seconds(), ttl) assert_config.assert_called_once()
def test_from_file(self): try: tmp = tempfile.mkdtemp() file_path = os.path.join(tmp, "foo.json") with open(file_path, "w") as fp: json.dump(dict(a=True), fp) Registry.from_file(file_path) self.assertEqual(dict(a=True), Registry()) Registry.set("a", False) self.assertFalse(Registry.get("a")) Registry.from_file(file_path) self.assertFalse(Registry.get("a")) finally: shutil.rmtree(tmp)
def test_get_artist(self, find, time, assert_config): time.return_value = 1 find.return_value = Artist(name="Queen") artist = LastService.get_artist("quueee") self.assertEqual(Artist(name="Queen"), artist) find.assert_called_once_with("quueee") artist, ttl = Registry.get("last.fm_artist_quueee") self.assertEqual({"name": "Queen"}, artist) self.assertEqual(timedelta(days=30, seconds=1).total_seconds(), ttl) assert_config.assert_called_once()
def test_cache(self, time): time.side_effect = [10, 20.1, 20.1, 20.5, 20.8] def callme(ttl, value, refresh=False): return Registry.cache( key="foo", ttl=timedelta(seconds=ttl), func=lambda: value, refresh=refresh, ) self.assertEqual("first", callme(10, "first")) self.assertEqual(("first", 20.0), Registry.get("foo")) self.assertEqual("second", callme(1, "second")) self.assertEqual(("second", 21.1), Registry.get("foo")) self.assertEqual("second", callme(1, "third")) self.assertEqual(("second", 21.1), Registry.get("foo")) self.assertEqual("third", callme(100, "third", refresh=True)) self.assertEqual(("third", 120.8), Registry.get("foo")) self.assertEqual(5, time.call_count)
def get_user(cls, username) -> User: """ Use last.fm api to fetch a user by name. The result will be cached for 24 hours. :param str username: The user's name :rtype: :class:`pydrag.User` """ cls.assert_config() cache = Registry.cache( key="last.fm_user_{}".format(username.lower()), ttl=timedelta(hours=24), func=lambda: User.find(username).to_dict(), ) return User(**cache)
def get_artist(cls, artist: str) -> Artist: """ Use last.fm api to find an artist by name. The result will be cached for 30 days. :param str artist: The artist's name to lookup :rtype: :class:`pydrag.Artist` """ cls.assert_config() cache = Registry.cache( key="last.fm_artist_{}".format(artist.lower()), ttl=timedelta(days=30), func=lambda: Artist.find(artist).to_dict(), ) return Artist(**cache)
def find(cls, **kwargs): def match(data, conditions): with contextlib.suppress(Exception): for k, v in conditions.items(): value = data.get(k) if callable(v): assert v(value) elif v is None: assert value is None else: assert type(value)(v) == value return True return False return [ cls.model(**raw) for raw in Registry.get(cls.namespace, default={}).values() if match(raw, kwargs) ]
def init_registry(self): cfg = os.path.join(click.get_app_dir("pytuber", False), "storage.db") Registry.from_file(cfg)
def get(cls, key, default=None): return Registry.get(cls.namespace, key, default=default)
def set(cls, *args, **kwargs): for key, value in kwargs.items(): Registry.set(cls.namespace, key, value)
def find_youtube_id(cls, id: str): return Registry.get(cls.namespace, id, "youtube_id", default=None)
def remove(cls, key): try: Registry.remove(cls.namespace, key) except KeyError: raise NotFound("No {} matched your argument: {}!".format( cls.namespace, key))
def update(cls, obj, data: Dict): new = attr.evolve(obj, **data) key = getattr(new, cls.key) Registry.set(cls.namespace, key, new.asdict()) return new
def tearDown(self): Registry().clear() super(TestCase, self).tearDown()
def cli(ctx: click.Context): """Create and upload music playlists to youtube.""" cfg = os.path.join(click.get_app_dir("pytuber", False), "storage.db") init_registry(cfg, version) ctx.call_on_close(lambda: Registry.persist(cfg))
def exists(cls, obj): key = getattr(obj, cls.key) return Registry.exists(cls.namespace, key)
def keys(cls): return list(Registry.get(cls.namespace, default={}).keys())