{ "info": { "author": "David Marin", "author_email": "dave@spendright.org", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "License :: OSI Approved :: Apache Software License", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5" ], "description": "Merge Scraper Data (for great justice!)\n=======================================\n\nThere are a lot of consumer campaigns out there on the Internet. Consumer\ncampaigns supported by perfectly lovely organizations, organized around\ncauses you wholeheartedly support, that would change the world if enough\npeople followed through on them.\n\nBut it's hard to put them into practice. And it's *really* hard to put more\nthan one campaign at a time into practice. Different campaigns have different\nscoring systems, different names for the same company, and, when they have\nthem at all, different apps that don't talk to each other.\n\n``msd`` takes messy data from a bunch of different consumer campaigns, and\nputs it into a single unified format.\n\n``msd`` currently powers `SpendRight `__\n(``msd``'s creator) and the `thinkContext `__ browser\nextension.\n\n\nUsing the data\n==============\n\nIf you're not there already, check out\n`msd's morph.io page `__, where you can\nview and download data merged from SpendRight's scrapers.\n\nKeep in mind that the original consumer campaigns are generally copyrighted by\nthe non-profits that created them, and they have all sorts of different\nterms/licensing agreements. It's up to you to decide whether to ask\nthem for permission now, or forgiveness later.\n\n(This mostly applies to the ``claim`` and ``rating`` tables; facts about\ncompanies and brands are almost certainly fair game.)\n\n\nInstallation\n============\n\nIt's on PyPI: ``pip install msd``\n\n\nUsage\n=====\n\n``msd db1.sqlite [db2.sqlite ...]``\n\nThis produces a file named ``msd.sqlite`` (you can change this with the ``-o``\nswitch).\n\n``msd`` can also take YAML files as input. The YAML files should encode a\nmap from table name to list of rows (which are maps from column name to value).\nFor example::\n\n campaign:\n - author: Greenpeace International\n campaign_id: greenpeace_palm_oil\n rating:\n - campaign_id: greenpeace_palm_oil\n company: Colgate-Palmolive\n judgment: -1\n - campaign_id: greenpeace_palm_oil\n company: Danone\n judgment: 0\n\nIf you don't have the library installed (e.g. for development), you\ncan use ``python -m msd.cmd`` in place of ``msd``.\n\n\nData format\n===========\n\n``msd`` uses a SQLite data format, both for input and output.\n\nThe input and output format are almost identical; differences are noted\nin *italics*.\n\nKeys\n----\n\nEvery campaign in the input data should have a ``campaign_id``\nthat would work as a Python identifier (for example ``wwf_palm_oil``).\n\nThere isn't a ``company_id`` field though; we just use the shortest name\nthat a company is commonly referred to by.``msd`` is smart\nenough to know that, for example, The Coca-Cola Company can be called\n``Coca-Cola`` but that we can't refer to The Learning Company as simply\n\"Learning\".\n\nSimilarly, there isn't a ``brand_id`` field, ``msd`` just figures out the\nproper name for the brand (minus the \u2122, etc.), and puts it into the ``brand``\nfield; the \"key\" for any given brand is ``company`` and ``brand`` together.\n\nThere also aren't (product) category keys; we just put the name of the\ncategory (e.g. ``Chocolate``) into the ``category`` field.\n\nFinally, the initial data sources each get a ``scraper_id``, which is one\nor more identifiers, separated by dots (e.g. ``sr.campaign.wwf_palm_oil``).\nThese serve only to help you track down problems in your input data.\n\n*Every table in the input data may have a* ``scraper_id`` *field to help\nidentify which code gathered that data. The stem\nof whatever input file data came from will be prepended to form the*\n``scraper_id`` *in the output.*\n\n*For example, a* ``scraper_id`` *of*\n``wwf_palm_oil`` *from an input file named* ``sr.campaign.sqlite``\n*would become* ``sr.campaign.wwf_palm_oil`` *in the output data.*\n\nMessy input data\n----------------\n\n``msd`` *can accept very, very messy input data. The goal is for you to be\nable as little effort as possible into writing scrapers.*\n\nno primary keys\n^^^^^^^^^^^^^^^\n\n*For starters, the input data need not have primary keys, or any keys at\nall. The first thing we do is shovel all the input data into a single\n\"scratch\" table anyways.*\n\n*It's totally fine to have two rows that* would *have the same keys in the\noutput data;* ``msd`` *will merge them for you.*\n\nmissing/extra fields\n^^^^^^^^^^^^^^^^^^^^\n\n*It's totally fine for the input data to be missing fields, or have\nfields set to* ``NULL`` *that are supposed to have a value (in the worst case,\nif you omit a required value,* ``msd`` *will just ignore that row.*\n\n*It's fine to have extra fields;* ``msd`` *will just ignore them.*\n\ndifferent names for companies and brands\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n*It's fine to use different names for the same company\nor brand;* ``msd`` *will figure this out and merge them as appropriate.*\n\ngeneral text cleanliness\n^^^^^^^^^^^^^^^^^^^^^^^^\n\n*For every text field,* ``msd`` *does the following things for you:*\n\n- *converts all whitespace (tabs, double spaces, etc.) to a single space*\n- *strips leading and trailing whitespace*\n- *converts \"smart quotes\", ligatures, and other silliness to the plain\n equivalent*\n- *normalizes all unicode into NFKD form (this basically means there aren't\n multiple ways to represent the same accented character).*\n\nbrand name cleaning\n^^^^^^^^^^^^^^^^^^^\n\n*In addition, you can be* even lazier *with the* ``brand`` *field.* ``msd``\n*automatically finds \u2122, \u00ae, etc., puts it elsewhere for safekeeping (see\nthe* ``tm`` *field, below), and ignores anything after it.*\n\n*For example, if you throw something like*\n``INVOKANA\u2122 (canagliflozin) USPI`` *into the* ``brand`` *field, it'll know\nthat the brand is named* ``INVOKANA`` *and is supposed to have a \u2122 after it.*\n\ncategory name cleaning\n^^^^^^^^^^^^^^^^^^^^^^\n\n``msd`` *formats category names in a consistent way. For example,*\n``food & beverages`` *in the input data would become* ``Food and Beverages``\n*in the output data.*\n\nrating cleanup\n^^^^^^^^^^^^^^\n\n``msd`` can do limited cleanup of ratings, including inferring ``judgment``\nfrom ``grade``. See ``rating`` table for details.\n\ninferred rows\n^^^^^^^^^^^^^\n\n``msd`` *will infer that companies and brands exist. For example, if you\ninclude a rating for a company in the* ``rating`` *table, a corresponding\nentry will be automatically created for you in the* ``company`` *table.*\n\nand that's not all...\n^^^^^^^^^^^^^^^^^^^^^\n\nNope, that's pretty much everything. Here are the table definitions:\n\n\nTable definitions\n-----------------\n\nbrand: facts about brands\n^^^^^^^^^^^^^^^^^^^^^^^^^\n\n**Primary Key**: ``company``, ``brand``\n\n**brand**: canonical name for the brand (e.g. ``Dove``)\n\n**company**: canonical name for the company (e.g. ``Unilever``)\n\n**facebook_url**: optional link to official Facebook page for the brand. (If\nthere's only a page for the company, put that in ``company.facebook_url``).\nSo consumers can say nice/brutally honest things on their Facebook page.\n\n**is_former**: 0 or 1. If 1, this brand no longer exists (e.g. Sanyo) or was\nsold to another company (e.g. LU is no longer owned by Groupe Danone). Set\nthis to 1 in your input data to knock out out-of-date brand information from\nout-of-date consumer campaigns.\n\n**is_licensed**: 0 or 1. If 1, this brand actually belongs to another company\n(e.g. The Coca-Cola Company markets products under the Evian brand).\nGenerally a good idea to put the responsiblity for a brand on its actual\nowner.\n\n**is_prescription**: 0 or 1. If 1, this brand is available by prescription\nonly (so you probably can't buy it on, like, Amazon.com).\n\n**logo_url**: 0 or 1. Optional link to an image of this brand's logo (need not\nbe on the brand's website).\n\n**tm**: empty string, ``\u2122``, ``\u00ae`` or ``\u2120``. The thing that companies like to\nappear directly after the brand name.\n\n**twitter_handle**: optional handle for the brand's Twitter account, including\nthe ``@`` (e.g. ``@BrownCowYogurt``). So consumers can congratulate them/call\nthem out on Twitter.\n\n**url**: optional link to official web site/page for this brand. It's okay\nif this is just a sub-page of the company's official website.\n\n\ncampaign: consumer campaigns\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nIn practice, introducing consumer campaigns to users is one of the\nmost important parts of any tool you build; you'll probably want to just use\nthis table as a starting point, and include some content of your own.\n\n**Primary Key**: ``campaign_id``\n\n**author**: optional free-form name of the organization behind the campaign\n(e.g. ``Greenpeace International``).\n\n**author_url**: optional link to author's website\n\n**campaign**: free-form name of the campaign (e.g.\n``Guide to Greener Electronics``)\n\n**campaign_id**: unique identifier for this campaign (e.g.\n``greenpeace_electronics``.) Up to you to pick something that makes sense\nand doesn't collide with other campaign IDs.\n\n**contributors**: optional free-form description of other contributors\nto the consumer campaign (e.g.\n``International Labor Rights Forum, Baptist World Aid``).\n\n**copyright**: optional copyright notice. Usually starts with ``\u00a9`` (e.g.\n``\u00a9 2006-2014 Climate Counts. All Rights Reserved.``).\n\n**date**: optional date this campaign was created, in ``YYYY-MM-DD``,\n``YYYY-MM``, or ``YYYY`` format. A string, not a number. Sometimes the\nbest available data is a couple years old, and consumers deserve to know!\n\n**donate_url**: optional link to a page where you can donate back to the\ncampaign/author. Try to include this somewhere in whatever you build; create a\nvirtuous cycle and help these consumer campaigns become financially\nself-sustaining!\n\n**email**: optional contact email for the campaign (e.g.\n``feedback@free2work.org``)\n\n**facebook_url**: optional link to official Facebook page for the campaign,\nso consumers can get involved in the movement!\n\n**goal**: very brief (40 characters or less) description of what someone\nhelps accomplish by being involved in this campaign (e.g.\n``stop forced labor in Uzbekistan``). Best to start this with a lowercase\nletter unless the first word is a proper noun.\n\n**twitter_handle**: optional handle for the campaign's Twitter account, so\nthat consumers can follow/reference them on Twitter. Including the ``@``\n(e.g. ``@WWF``).\n\n**url**: optional link to campaign's web site, so consumers can learn more\nand get involved.\n\n\ncategory: product categories for companies and brands\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n``msd`` doesn't build an organized category tree like, say, online retailers\nhave; these are more like hints. See the ``subcategory`` table for details.\n\n**Primary Key**: ``company``, ``brand``, ``category``\n\n**brand**: canonical name for the brand. Empty string if we're categorizing\na company\n\n**category**: free-form name for category (e.g. ``Food and Beverages``).\n\n**company**: canonical name for the company\n\n**is_implied**: 0 or 1. If 1, this category was only implied by a subcategory\nrelationship (see ``subcategory`` table). *Ignored in the input data.*\n\n\nclaim: bullet points to support ratings\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n**Primary Key**: ``campaign_id``, ``company``, ``brand``, ``scope``, ``claim``\n\n(``claim`` is free-form, so this is more like a non-unique key)\n\n**brand**: canonical name for the brand. Empty string if this is a claim\nabout a company.\n\n**campaign_id**: unique identifier of campaign making this claim (see\n``campaign.campaign_id``)\n\n**claim**: free-form claim. Should be small enough to fit in a bullet point,\nand be able to stand on its own (spell out obscure acronyms and other context).\nBest to start this with a lowercase letter unless the first word is a\nproper noun.\n\n**company**: canonical name for the company\n\n**date**: optional date this claim was made, in ``YYYY-MM-DD``,\n``YYYY-MM``, or ``YYYY`` format. A string, not a number.\n\n**judgment**: -1, 0, or 1. Does the claim say something good (``1``), mixed\n(``0``), or bad (``-1``) about the company or brand? Need not match the\ncampaign's rating. If a claim is totally neutral (e.g.\n``manufactures large appliances``) it doesn't belong in this table at all!\n\n**scope**: optional free-form limitation on which products this applies to\n(e.g. ``Fair Trade``). Usually an empty string, to mean no limitation or that\nit's only *not* some scope elsewhere in the data (don't set this to\n``Non-Certified``).\n\n**url**: optional link to web page/PDF document etc. where this claim was made.\nSome people like to see the supporting data!\n\n\ncompany: facts about companies\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n**Primary Key**: ``company``\n\n**company**: canonical name for the company (e.g. ``Disney``)\n\n**company_full**: full, official name of the company (e.g.\n``The Walt Disney Company``).\n\n**email**: contact/feedback email for the company (e.g.\n``consumer.relations@adidas.com``).\n\n**facebook_url**: optional link to official Facebook page for the company.\n\n**feedback_url**: optional link to a page where consumers can submit\nfeedback to the company (some companies don't like to do this by email).\n\n**hq_company**: optional name of the country where this company is\nheadquartered (e.g. ``USA``).\n\n**logo_url**: 0 or 1. Optional link to an image of this company's logo (need\nnot be on the company's website).\n\n**phone**: optional phone number for customer feedback/complaints (a string,\nnot a number)\n\n**twitter_handle**: optional handle for the company's Twitter account,\nincluding the ``@`` (e.g. ``@Stonyfield``).\n\n**url**: optional link to official web site/page for this company.\n\n\ncompany_name: canoncial, full, and alternate names for companies\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n**Primary Key**: ``company``, ``company_name``\n\n**company**: canonical name for the company (e.g. ``Disney``)\n\n**company_name**: a name for the company. can be the canonical\nname, the full name (see ``company.company_full``) or something else\n(e.g. ``Walt Disney``).\n\n**is_alias**: 0 or 1. If 1, this is a name that somebody used somewhere\nbut isn't really a recognizable name for the company (e.g. \"AEO\" for\nAmerican Eagle Outfitters or \"LGE\" for \"LG Electronics\"). *Set this your\ninput data to knock out weird company aliases.*\n\n**is_full**: 0 or 1. If 1, this is the full name for the company,\nwhich also appears in ``company.company_full``. (There isn't an\n``is_canonical`` field; just check if ``company = company_name``.)\n\n\nrating: campaigns' judgments of brands and companies\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nThis is where the magic happens.\n\n**brand**: canonical name for the brand. Empty string if this is a rating of\na company.\n\n**campaign_id**: unique identifier of campaign this rating comes from (see\n``campaign.campaign_id``)\n\n**company**: canonical name for the company\n\n**date**: optional date this rating was last updated, in ``YYYY-MM-DD``,\n``YYYY-MM``, or ``YYYY`` format. A string, not a number.\n\n**description**: free-form, brief description of the rating (e.g.\n``Soaring``, ``Cannot Recommend``).\n\n**grade**: optional letter grade (e.g. ``A+``, ``C-``, ``F``). Some campaigns\nuse ``E`` instead of ``F``.\n\n**judgment**: -1, 0, or 1. Should consumers support (``1``), consider\n(``0``), or avoid (``-1``) the company or brand? Some campaigns will give\neverything a ``1`` (e.g. certifiers) or everything a ``-1`` (e.g. boycott\ncampaigns).\n\n``msd`` *can infer* ``judgment`` *from* ``grade``, *but otherwise you need\nto set it yourself in the input data.*\n\n*Red for avoid, yellow for consider, and green for support is a de-facto\nstandard among consumer campaigns. If all else fails, contact the campaign's\nauthor and ask.*\n\n**max_score**: if ``score`` is set, the highest score possible on the rating\nscale (a number).\n\n**min_score**: if ``score`` is set, the lowest score possible on the rating\nscale (a number). *If* ``score`` *is set but* ``min_score`` *is not,* ``msd``\n*will assume* ``min_score`` *is zero.*\n\n**num_ranked**: if ``rank`` is set, the number of things ranked (an integer)\n\n**rank**: if campaign ranks companies/brands, where this one ranks\n(this is an integer, and the best ranking is `1`, not `0`).\n\n**scope**: optional free-form limitation on which products this applies to\n(e.g. ``Fair Trade``). Usually an empty string, to mean no limitation or that\nit's only *not* some scope elsewhere in the data (don't set this to\n``Non-Certified``).\n\n**score**: optional numerical score (e.g. ``57.5``).\n\n**url**: optional link to web page/PDF document etc. where this rating was\nmade. Some people like to see the supporting data!\n\n\nscraper: when data was last gathered\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n**Primary Key**: ``scraper_id``\n\n**last_scraped**: when this data was last gathered, as a UTC ISO timestamp\n(for example, ``2015-08-03T20:55:36.795227Z``).\n\n**scraper_id**: unique identifier for the scraper that gathered this data\n\n\nscraper_brand_map: names of brands in the input data\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nThis is mostly useful for debugging your output data.\n\n``msd`` *ignores this table if it appears in the input data*\n\n**Primary Key**: ``scraper_id``, ``scraper_company``, ``scraper_brand``\n\n**Other Indexes**: (``company``, ``brand``)\n\n**brand**: canonical name for the brand. (This should never be empty;\nthat's what ``scraper_company_map`` is for.)\n\n**company**: canonical name for the company\n\n**scraper_brand**: name used for the brand in the input data\n\n**scraper_company**: name used for the company in the input data\n\n**scraper_id**: unique identifier for the scraper that used this\nbrand and company name\n\n\nscraper_category_map: names of categories in the intput data\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nThis is mostly useful for debugging your output data.\n\n``msd`` *ignores this table if it appears in the input data*\n\n**Primary Key**: ``scraper_id``, ``category``, ``scraper_brand``\n\n**Other Indexes**: (``category``)\n\n**category**: canonical name for a category (e.g. ``Food and Beverages``)\n\n**scraper_brand**: name used for the brand in the input data (e.g.\n`` food & beverages``).\n\n**scraper_id**: unique identifier for the scraper that used this\ncategory name\n\n\nscraper_company_map: names of companies in the input data\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nThis is mostly useful for debugging your output data.\n\n``msd`` *ignores this table if it appears in the input data*\n\n**Primary Key**: ``scraper_id``, ``scraper_company``\n\n**Other Indexes**: (``company``)\n\n**company**: canonical name for the company\n\n**scraper_brand**: name used for the brand in the input data\n\n**scraper_id**: unique identifier for the scraper that used this\ncompany name\n\n\nsubcategory: product category relationships\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n``msd`` doesn't attempt to build a proper category tree; it's really just\na directed graph of category relationships: if something is in category\nA (``subcategory``) it must also be in category B (``category``).\n\n``msd`` *automatically infers implied relationships: if A is a subcategory\nof B and B is a subcategory of C, A is a subcategory of C.*\n\n**category**: canonical name for a category\n\n**is_implied**: 0 or 1. If 1, this relationship was inferred by ``msd``.\n*Ignored in the input data.*\n\n**subcategory**: canonical name for a subcategory of ``category``\n\n\nurl: hook for scraping URLs in the scraper data\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n*This table only exists in the input data, and is only used to fill fields\nin the output data that would otherwise be empty.*\n\nThis allows us to build generic scrapers that can grab Twitter handles,\nFacebook URLs, etc. directly from a company or brand's official page. See\nSpendRight's `scrape-urls `__\nfor an example.\n\n**facebook_url**: optional facebook page for a company/brand\n\n**last_scraped**: when the company/brand's page was scraped, as a UTC\niso timestamp (e.g. ``2015-08-03T20:55:36.795227Z``). *Not currently used.*\n\n**twitter_handle**: optional twitter handle for a company/brand, including\nthe leading ``@``.\n\n**url**: url this data was scraped from\n\n\nWriting your own scrapers\n=========================\n\nIf you want to write something in Python, check out SpendRight's\n`scrape-campaigns `__\nproject, and submit a pull request (look in ``scrapers/``) for examples.\n\nIf you'd rather write in another language, consider setting up your own\nscraper on `morph.io `__, which can also handle scrapers\nin Ruby, PHP, Perl, and Node.js. See the\n`morph.io Documentation `__ for details.\nAnd let us know, so we can point\n`msd's morph.io page `__ at it.\n\n\nWorking on msd\n==============\n\n``msd`` is pretty straightforward. Here's a brief overview of how it works:\n\n1. ``msd`` starts in ``msd/cmd.py`` (look for ``msd.cmd.run()``).\n2. It first dumps all the input data into a temporary \"scratch\" DB\n (``msd-scratch.sqlite``) with the correct columns and useful indexes (look\n for ``msd.scratch.build_scratch_db()``).\n3. Then it creates the output database (``msd.sqlite``) and fills it table by\n table (look for ``msd.fill_output_db()``).\n\nAlso, table definitions live in ``msd/table.py``.\n\n\nUsing msd as a library\n======================\n\n``msd`` isn't really a library, but there's some useful stuff in ``msd``\n(for example, ``msd/company.py`` knows how to strip all the various versions\nof \"Inc.\" off company names).\n\nIf you want to call some of this stuff from another project, please let us\nknow so that we can work out a sane, stable interface for you!", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/spendright/msd", "keywords": null, "license": "Apache", "maintainer": null, "maintainer_email": null, "name": "msd", "package_url": "https://pypi.org/project/msd/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/msd/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://github.com/spendright/msd" }, "release_url": "https://pypi.org/project/msd/0.1.5/", "requires_dist": null, "requires_python": null, "summary": "Merge SpendRight scraper data", "version": "0.1.5" }, "last_serial": 2122729, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "bc9d24c10c56d2f10b185da117c4e062", "sha256": "a8e4d929481e3b928747c655f5b97313847372074fe87ea1bb7fe2dc261ef78d" }, "downloads": -1, "filename": "msd-0.1.0.tar.gz", "has_sig": false, "md5_digest": "bc9d24c10c56d2f10b185da117c4e062", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 26976, "upload_time": "2015-09-14T18:59:20", "url": "https://files.pythonhosted.org/packages/db/40/995e3b9eea4455a76ae1d3ada765d9a3d3c4d910646efb96f5077ca893b8/msd-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "52ff0a037936ba20b7d53143556f372b", "sha256": "293a2909a0dfe98d7c009970b9fb2a16cc53022a0eb11c1e2474607f1e71e3c8" }, "downloads": -1, "filename": "msd-0.1.1.tar.gz", "has_sig": false, "md5_digest": "52ff0a037936ba20b7d53143556f372b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 27059, "upload_time": "2015-09-14T19:43:06", "url": "https://files.pythonhosted.org/packages/50/9a/26f78b715e955b19fe9ec1741a3ec66467f3530cd0b50262fb3446b4d272/msd-0.1.1.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "9ae385f1d0a88e3c6e9a4e2c5fb4ae7a", "sha256": "a475ee7bc7e6411bb79533352b5f07f1179768b211ba8cf840a15638fb352fee" }, "downloads": -1, "filename": "msd-0.1.2.tar.gz", "has_sig": false, "md5_digest": "9ae385f1d0a88e3c6e9a4e2c5fb4ae7a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 27056, "upload_time": "2015-09-19T05:20:54", "url": "https://files.pythonhosted.org/packages/6d/7d/a1a80179815d6f2fa3c0d2c8c5136fda273842f30f9859b1ecae8b560b1d/msd-0.1.2.tar.gz" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "c440b3b1e8c089e9ac2d4fff6bd854b7", "sha256": "78ba0efbaa9d496501696ea523c846648a710b7b2cad7fefcbd37e2869375044" }, "downloads": -1, "filename": "msd-0.1.3.tar.gz", "has_sig": false, "md5_digest": "c440b3b1e8c089e9ac2d4fff6bd854b7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 27210, "upload_time": "2016-02-09T00:32:17", "url": "https://files.pythonhosted.org/packages/0f/c3/784c2511bbc1394ea7d7a70249026944d4553d057dc940d446abe151714a/msd-0.1.3.tar.gz" } ], "0.1.4": [ { "comment_text": "", "digests": { "md5": "c30611a3c3a808e13d95d59b88978a8a", "sha256": "1880717d0e70f4503dfd4e47ffa2d32575db12d32adaabd5c5fc5bcfece3ad56" }, "downloads": -1, "filename": "msd-0.1.4.tar.gz", "has_sig": false, "md5_digest": "c30611a3c3a808e13d95d59b88978a8a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 27753, "upload_time": "2016-05-11T23:06:46", "url": "https://files.pythonhosted.org/packages/9a/89/86acfd3605bc7c31f44910904c8afa33c5d72642bd6b14c589ae437a698b/msd-0.1.4.tar.gz" } ], "0.1.5": [ { "comment_text": "", "digests": { "md5": "eb2d8de8e3512c2017c0ab90f1bc7b2a", "sha256": "2d6690048c4dc770cfdec20a729207e647dfced77953cde2a67215f6b8ccf12b" }, "downloads": -1, "filename": "msd-0.1.5.tar.gz", "has_sig": false, "md5_digest": "eb2d8de8e3512c2017c0ab90f1bc7b2a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 27780, "upload_time": "2016-05-19T00:07:09", "url": "https://files.pythonhosted.org/packages/5c/65/aea162d245319793f7bebdbbbb42fb9559e1bba1dc593d7fc0dfadd54162/msd-0.1.5.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "eb2d8de8e3512c2017c0ab90f1bc7b2a", "sha256": "2d6690048c4dc770cfdec20a729207e647dfced77953cde2a67215f6b8ccf12b" }, "downloads": -1, "filename": "msd-0.1.5.tar.gz", "has_sig": false, "md5_digest": "eb2d8de8e3512c2017c0ab90f1bc7b2a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 27780, "upload_time": "2016-05-19T00:07:09", "url": "https://files.pythonhosted.org/packages/5c/65/aea162d245319793f7bebdbbbb42fb9559e1bba1dc593d7fc0dfadd54162/msd-0.1.5.tar.gz" } ] }