{ "info": { "author": "\u041d\u0438\u043a\u043e\u043b\u0430 \"hauzer\" \u0412\u0443\u043a\u043e\u0441\u0430\u0432\u0459\u0435\u0432\u0438\u045b", "author_email": "hauzer@gmx.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Topic :: Software Development :: Libraries" ], "description": "Features\n========\n\n- Supports all packages and methods listed at http://www.last.fm/api.\n\n- Methods return plain Python types: dictionaries and lists.\n\n- If the user wishes, the library can make an application comply to the point 4.4 of\n `Last.fm's API ToS `_, which says that the request\n rate of an application must be limited.\n\n- Handles all Last.fm API errors via exceptions.\n\n- Easily extendible.\n\n|\n\nA tutorial\n==========\n\nA short introduction\n--------------------\n\n*lfm.App*\n~~~~~~~~~\n\nInstantiate a Last.fm application::\n\n from lastfm import lfm\n \n app = lfm.App(API_KEY, SECRET)\n\nThe above is self-explanatory. You'll need an API key and the corresponding \"secret\"\ngiven by Last.fm. If you don't have those handy, you can ommit them for **testing**\npurposes, as *lfm* comes with its own. You are expected to provide your own key and\nsecret in real applications.\n\nIf you want your application to comply to Last.fm's request rate limit, you'll need\nto provide a third argument, a file in which a sqlite3 database which tracks requests\nwill be stored.\n\n::\n \n LFM_FILE = \"lfm.dat\"\n \n app = lfm.App(API_KEY, SECRET, LFM_FILE)\n\nAs a fourth argument, you can provide a tuple of your program's name and version,\nto be used in the user-agent::\n\n NAME = \"myprogram\"\n VERSION = \"1.0.0\"\n \n app = lfm.App(API_KEY, SECRET, LFM_FILE, (NAME, VERSION))\n \nThe user-agent is formatted as \"NAME/VERSION lfm/LFMVERSION\". If you don't provide\nthis information, both the name and version will be \"unknown\".\n\n\nMethods and packages\n~~~~~~~~~~~~~~~~~~~~\n\nAPI methods are organized like so::\n\n data = app.package.method_name(...)\n \nSo, if you wanted to, for example, fetch all recently listened tracks of a user,\nyou'd do something like this::\n\n tracks = app.user.get_recent_tracks(user)\n \nNote the underscores. Last.fm uses *camelCase* for method names. Such a thing\nisn't Pythonic, though, hence the transformation of names to *under_scores*.\n\n\nAuthenticating\n--------------\n\n*auth.get_mobile_session()*\n~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nLet's get a user's session now. There are three ways to do this. The first one\nis by supplying a username and a password::\n\n session = app.auth.get_mobile_session(user, pwd)\n\n\n*auth.get_session()*\n~~~~~~~~~~~~~~~~~~~~\n \nThe second one is more complicated, but more secure and trustworthy. First,\nyou need to fetch a token::\n\n token = app.auth.get_token()\n \nThen you have to make the user authenticate the token by pointing him to the\nauthentication web-page::\n\n import webbrowser\n \n webbrowser.open(token.url)\n input(\"Press enter after granting access.\")\n \nAfter the user has granted access, all that's left is to fetch the session::\n\n session = app.auth.get_session(token)\n\n\n*auth.get_url()*\n~~~~~~~~~~~~~~~~~~~~\n\nThe third one is for web apps. `auth.get_url()` takes one argument, a callback URL,\nand returns an URL which points to the authentication page. When the user\nauthenticates, the page redirects to the callback URL with the token appended as a\nGET parameter. \nFor more information, consult the `official Last.fm documentation `_.\n\n\nUsing the session\n~~~~~~~~~~~~~~~~~\n\nRegardless of which of the methods you use, a session needs to be bound to your\napp by assigning the session key to the *App*'s *session_key* attribute::\n\n app.session_key = session[\"key\"]\n\nThat's all. You can now call methods which require authentication::\n\n app.track.remove_tag(artist, track, tag)\n \n\nMore\n----\n\nFor more information on specific methods, consult the `API page `_\non Last.fm.\n\n|\n\nAn advanced tutorial\n====================\n\nCustom requests\n---------------\n\nSay, for example, that Last.fm has added a new method not yet available in\nthis library. What can be done then? The solution is actually quite straightforward:\nuse *App.request()*. You can manually specify the API package, method and parameters::\n\n def playlist_remove(app, playlist_id):\n params = {\n \"playlistID\": playlist_id,\n }\n \n return app.request(\"playlist\", \"remove\", params)\n\nSimple as that.\n\n\nAdding new packages\n-------------------\n\n*App.request_auto()*\n~~~~~~~~~~~~~~~~~~~~~~~~\n\nWhat if, by some miracle, a whole new package with a bunch of methods was added?\nYou'd want to use those methods several times in your program. Calling *request()*\nevery time would be quite cumbersome; very repetitive and error-prone.\n\nWell, an unlikely hero arises: *App.request_auto()*! This function tries\nto automate every bit of requesting that can possibly be automated, and generally\nsucceeds very well! This whole library is built on that one function. Here's an\nexample from the source itself::\n\n class Track(Package):\n \n ...\n \n def get_info(self, artist = None, track = None, username = None, autocorrect = None, mbid = None):\n data = self.app.request_auto()\n return data[\"track\"]\n \n ...\n\nWhat kind of magick is this? Well, without going into too much detail\n(open source, remember?), the function cleverly learns all of the three,\nif possible: the package, the method, the parameters:\n\n- It assembles the method name from the caller function's name; \"getInfo\"\n in this case.\n \n- The parameters, ignoring *self*, are grabbed from the caller's arguments.\n Parameter names are stripped of trailing underscores, to allow the use of\n parameters such as *from*.\n True to the Python's philosophy of \"duck-tape\" programming, the function tries\n to accept all kinds of types as parameters. It handles all primitive ones well:\n integers, floats, booleans, and such. Of the more complicated types, it can\n handle lists, but not dictionaries.\n \n- The name of the package is learned from the name of the class the function's\n in, but **only** if the class inherits *lfm.Package*.\n \n*request_auto()* is not only intelligent and elegant, it's also flexible.\nYou can override any of the three::\n\n def get_info(self, artist = None, track = None, username = None, autocorrect = None, mbid = None):\n package = \"the_correct_package_name\"\n method = \"the_correct_method_name\"\n \n params = {\n \"special\" : 0xDEADBEEF,\n \"mbid\" : None,\n }\n \n data = self.app.request_auto(package, method, params)\n return data[\"track\"]\n \nSo, we have added a new parameter called *special*, and made *mbid*\nalways *None*, whatever the user may have passed. Pretty neat, huh?\nNote that *params* will be **merged into** the auto-gathered\ndictionary of parameters, not overwrite them. \n\n\nInheriting *Package*\n~~~~~~~~~~~~~~~~~~~~\n\nVery well, your custom-made Package would look something like this::\n\n class Forum(Package):\n def post(self, threadid, msg):\n data = self.app.request_auto()\n return data\n \nAnd you'd use it like so::\n\n forum = Forum(app)\n forum.post(\"1832723\", \"Hello folks!\")\n\n\nInheriting *App*\n~~~~~~~~~~~~~~~~\n\nTo add the finishing touch, you could extend *App*::\n\n class App(lfm.App):\n forum = None\n \n def __init__(self, key, secret, db = None, info = None):\n super().__init__(key, secret, db, info)\n \n forum = Forum(self)\n\nAnd with that::\n\n app.forum.post(\"1832723\", \"Hello folks!\")", "description_content_type": null, "docs_url": null, "download_url": "https://bitbucket.org/hauzer/lfm/downloads", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://bitbucket.org/hauzer/lfm/", "keywords": null, "license": "GPLv3", "maintainer": null, "maintainer_email": null, "name": "lfmh", "package_url": "https://pypi.org/project/lfmh/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/lfmh/", "project_urls": { "Download": "https://bitbucket.org/hauzer/lfm/downloads", "Homepage": "https://bitbucket.org/hauzer/lfm/" }, "release_url": "https://pypi.org/project/lfmh/1.1.1/", "requires_dist": null, "requires_python": null, "summary": "A Last.fm API interface.", "version": "1.1.1" }, "last_serial": 1063005, "releases": { "1.0.0": [ { "comment_text": "", "digests": { "md5": "849f9fdf6fe0fc5e5ce6920c6b9f4e84", "sha256": "343507de12f85c762311d05b75f3854a0b3097ff3bd50ba55824c87ff829532f" }, "downloads": -1, "filename": "lfmh-1.0.0.zip", "has_sig": false, "md5_digest": "849f9fdf6fe0fc5e5ce6920c6b9f4e84", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 39073, "upload_time": "2013-07-23T13:20:53", "url": "https://files.pythonhosted.org/packages/bc/bc/f11cbef5784ab4f64249b0205d97192dc51bc94c7943c7148597a2ea90eb/lfmh-1.0.0.zip" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "debc113ec17b99acc2c0b4abc02d7581", "sha256": "ff514b1828a28391c6a90764255fd1df30f74d5c3bdf9e0f109eed9eea43d737" }, "downloads": -1, "filename": "lfmh-1.0.1.zip", "has_sig": false, "md5_digest": "debc113ec17b99acc2c0b4abc02d7581", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 39069, "upload_time": "2013-07-23T13:32:48", "url": "https://files.pythonhosted.org/packages/4f/d1/fb75eb5febbfd6f6fc6f588117c9d14f8283c2085ba1c50feb048d7def98/lfmh-1.0.1.zip" } ], "1.0.2": [], "1.0.3": [ { "comment_text": "", "digests": { "md5": "75c47612cbb3259517c0186516171d77", "sha256": "55b070fce484514947903d0a330fd787446206b4f40ccef6595f406454090ea8" }, "downloads": -1, "filename": "lfmh-1.0.3.zip", "has_sig": false, "md5_digest": "75c47612cbb3259517c0186516171d77", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 48817, "upload_time": "2013-07-29T06:37:49", "url": "https://files.pythonhosted.org/packages/21/06/fe7eb3746b8121c288788f08e10c6e2f1c83ea495e3c2ab4b0f4fdfbb456/lfmh-1.0.3.zip" } ], "1.0.4": [ { "comment_text": "", "digests": { "md5": "a93aa1c99807eb343ccd62965c20b56e", "sha256": "a732ae8ded676d888b2f29c29a7ed09f53f2f2baa16524196c5e57296809cac5" }, "downloads": -1, "filename": "lfmh-1.0.4.tar.gz", "has_sig": false, "md5_digest": "a93aa1c99807eb343ccd62965c20b56e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 30806, "upload_time": "2014-03-29T18:48:23", "url": "https://files.pythonhosted.org/packages/56/a7/6c9aa72999f3a503601538282d3a3ee72b4944ede050aae35886018c13bf/lfmh-1.0.4.tar.gz" } ], "1.0.5": [ { "comment_text": "", "digests": { "md5": "ef63e81f2e1934df275b58b6b6087c47", "sha256": "6d72a50c91f054f233bd2cc80f4f23e1d8f34bb3d9d9e66f3ab1aec8cbd12ace" }, "downloads": -1, "filename": "lfmh-1.0.5.tar.gz", "has_sig": false, "md5_digest": "ef63e81f2e1934df275b58b6b6087c47", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 30897, "upload_time": "2014-03-30T13:26:30", "url": "https://files.pythonhosted.org/packages/57/68/a363d49721ef28868db2c716d24c3d1d735e6fcbeede7a02b672d6eee557/lfmh-1.0.5.tar.gz" } ], "1.1.0": [ { "comment_text": "", "digests": { "md5": "cb575c4e6afaa1da04cb357841b79fb9", "sha256": "b5dc755015b788baf306c9c0bbb9c6c958766a950e589caba956568de478c379" }, "downloads": -1, "filename": "lfmh-1.1.0.tar.gz", "has_sig": false, "md5_digest": "cb575c4e6afaa1da04cb357841b79fb9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 27262, "upload_time": "2014-03-30T18:11:08", "url": "https://files.pythonhosted.org/packages/76/ab/55c9f4d47a4f5da9966db5bbf8b133b319553b663217933dadfb9bd513bc/lfmh-1.1.0.tar.gz" } ], "1.1.1": [ { "comment_text": "", "digests": { "md5": "4dbfe26a38237aaff3b0f9bbdf745ea5", "sha256": "37ef96ed423bb0f2539f52b0d8fea0558c1d90ed9c60f159c31f480018d6ceec" }, "downloads": -1, "filename": "lfmh-1.1.1.zip", "has_sig": false, "md5_digest": "4dbfe26a38237aaff3b0f9bbdf745ea5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 34333, "upload_time": "2014-04-17T01:22:01", "url": "https://files.pythonhosted.org/packages/74/69/ae1cc737677fd3c45f7aa52d36465294385719cb085b20e2cd2f99ae7bd8/lfmh-1.1.1.zip" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "4dbfe26a38237aaff3b0f9bbdf745ea5", "sha256": "37ef96ed423bb0f2539f52b0d8fea0558c1d90ed9c60f159c31f480018d6ceec" }, "downloads": -1, "filename": "lfmh-1.1.1.zip", "has_sig": false, "md5_digest": "4dbfe26a38237aaff3b0f9bbdf745ea5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 34333, "upload_time": "2014-04-17T01:22:01", "url": "https://files.pythonhosted.org/packages/74/69/ae1cc737677fd3c45f7aa52d36465294385719cb085b20e2cd2f99ae7bd8/lfmh-1.1.1.zip" } ] }