├── .coveragerc ├── .editorconfig ├── .gitignore ├── .travis.yml ├── LICENSE.txt ├── Makefile ├── README.md ├── mtgsdk ├── __init__.py ├── card.py ├── changelog.py ├── config.py ├── querybuilder.py ├── restclient.py ├── set.py ├── subtype.py ├── supertype.py └── type.py ├── setup.cfg ├── setup.py ├── tests ├── __init__.py ├── test_card.py ├── test_changelog.py ├── test_config.py ├── test_mtgexception.py ├── test_set.py ├── test_subtype.py ├── test_supertype.py └── test_type.py └── tox.ini /.coveragerc: -------------------------------------------------------------------------------- 1 | # This file is part of mtgsdk. 2 | # https://github.com/MagicTheGathering/mtg-sdk-python 3 | 4 | # Licensed under the MIT license: 5 | # http://www.opensource.org/licenses/MIT-license 6 | # Copyright (c) 2016, Andrew Backes 7 | 8 | [run] 9 | omit = 10 | *tests.py 11 | branch = True 12 | source = 13 | mtgsdk 14 | 15 | [report] 16 | exclude_lines = 17 | pragma: no cover 18 | def __repr__ 19 | raise NotImplementedError 20 | if __name__ == .__main__.: 21 | from urllib.parse import parse_qs 22 | except ImportError: 23 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig: a universal project-level configuration file 2 | # See https://editorconfig.org/#download to get a plugin for your text editor or IDE 3 | 4 | root = true 5 | 6 | [*] 7 | indent_size = 4 8 | indent_style = space 9 | charset = utf-8 10 | trim_trailing_whitespace = true 11 | insert_final_newline = true 12 | end_of_line = lf 13 | 14 | [Makefile] 15 | indent_style = tab 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # This file is part of mtgsdk. 2 | # https://github.com/MagicTheGathering/mtg-sdk-python 3 | 4 | # Licensed under the MIT license: 5 | # http://www.opensource.org/licenses/MIT-license 6 | # Copyright (c) 2016, Andrew Backes 7 | 8 | # Byte-compiled / optimized / DLL files 9 | __pycache__/ 10 | *.py[cod] 11 | 12 | # C extensions 13 | *.so 14 | 15 | # Distribution / packaging 16 | .Python 17 | env/ 18 | bin/ 19 | build/ 20 | develop-eggs/ 21 | dist/ 22 | eggs/ 23 | lib/ 24 | lib64/ 25 | parts/ 26 | sdist/ 27 | var/ 28 | *.egg-info/ 29 | .installed.cfg 30 | *.egg 31 | 32 | # Installer logs 33 | pip-log.txt 34 | pip-delete-this-directory.txt 35 | 36 | # Unit test / coverage reports 37 | htmlcov/ 38 | .tox/ 39 | .coverage 40 | .cache 41 | nosetests.xml 42 | coverage.xml 43 | 44 | # Translations 45 | *.mo 46 | 47 | # Mr Developer 48 | .mr.developer.cfg 49 | .project 50 | .pydevproject 51 | 52 | # Rope 53 | .ropeproject 54 | 55 | # Django stuff: 56 | *.log 57 | *.pot 58 | 59 | # Sphinx documentation 60 | docs/_build/ 61 | 62 | # Fixtures 63 | fixtures/*.yaml 64 | 65 | # IDE stuff: 66 | .idea/ 67 | .vscode/ 68 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # This file is part of mtgsdk. 2 | # https://github.com/MagicTheGathering/mtg-sdk-python 3 | 4 | # Licensed under the MIT license: 5 | # http://www.opensource.org/licenses/MIT-license 6 | # Copyright (c) 2016, Andrew Backes 7 | 8 | language: python 9 | 10 | python: 11 | - "3.6" 12 | 13 | install: 14 | # install python requirements 15 | - make setup 16 | 17 | script: 18 | # run tests 19 | - make test 20 | 21 | after_success: 22 | - coveralls 23 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Andrew Backes 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # This file is part of mtgsdk. 2 | # https://github.com/MagicTheGathering/mtg-sdk-python 3 | 4 | # Licensed under the MIT license: 5 | # http://www.opensource.org/licenses/MIT-license 6 | # Copyright (c) 2016, Andrew Backes 7 | 8 | # lists all available targets 9 | list: 10 | @sh -c "$(MAKE) -p no_targets__ | awk -F':' '/^[a-zA-Z0-9][^\$$#\/\\t=]*:([^=]|$$)/ {split(\$$1,A,/ /);for(i in A)print A[i]}' | grep -v '__\$$' | grep -v 'make\[1\]' | grep -v 'Makefile' | sort" 11 | # required for list 12 | no_targets__: 13 | 14 | # install all dependencies (do not forget to create a virtualenv first) 15 | setup: 16 | @pip install -U -e .\[tests\] 17 | 18 | # test your application (tests in the tests/ directory) 19 | test: unit 20 | 21 | unit: 22 | @coverage run --branch `which nosetests` -vv --with-yanc -s tests/ 23 | @coverage report -m --fail-under=80 24 | 25 | # show coverage in html format 26 | coverage-html: unit 27 | @coverage html 28 | 29 | # run tests against all supported python versions 30 | tox: 31 | @tox 32 | 33 | #docs: 34 | #@cd mtgsdk/docs && make html && open _build/html/index.html 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [EditorConfig]: https://editorconfig.org/#download 2 | 3 | # Magic: The Gathering SDK 4 | 5 | [![mtg-developers on discord](https://img.shields.io/badge/discord-mtg%20developers-738bd7.svg)](https://discord.gg/qwGJNnP) 6 | [![PyPI version](https://badge.fury.io/py/mtgsdk.svg)](https://badge.fury.io/py/mtgsdk) 7 | [![Build Status](https://travis-ci.org/MagicTheGathering/mtg-sdk-python.svg?branch=master)](https://travis-ci.org/MagicTheGathering/mtg-sdk-python) 8 | [![Requirements Status](https://requires.io/github/MagicTheGathering/mtg-sdk-python/requirements.svg?branch=master)](https://requires.io/github/MagicTheGathering/mtg-sdk-python/requirements/?branch=master) 9 | [![Code Climate](https://codeclimate.com/github/MagicTheGathering/mtg-sdk-python/badges/gpa.svg)](https://codeclimate.com/github/MagicTheGathering/mtg-sdk-python) 10 | [![Coverage Status](https://coveralls.io/repos/github/MagicTheGathering/mtg-sdk-python/badge.svg?branch=master)](https://coveralls.io/github/MagicTheGathering/mtg-sdk-python?branch=master) 11 | 12 | This is the Magic: The Gathering SDK Python implementation. It is a wrapper around the MTG API of [magicthegathering.io](http://magicthegathering.io/). 13 | 14 | ## Requirements 15 | Python 3 is currently the only supported version for the sdk. More specifically, the package was developed using Python 3.4. 16 | 17 | ## Installation 18 | 19 | Using pip: 20 | 21 | pip install mtgsdk 22 | 23 | ## Usage 24 | 25 | Import (Card and Set will be most used) 26 | 27 | from mtgsdk import Card 28 | from mtgsdk import Set 29 | from mtgsdk import Type 30 | from mtgsdk import Supertype 31 | from mtgsdk import Subtype 32 | from mtgsdk import Changelog 33 | 34 | ### Properties Per Class 35 | 36 | #### Card 37 | 38 | name 39 | multiverse_id 40 | layout 41 | names 42 | mana_cost 43 | cmc 44 | colors 45 | color_identity 46 | type 47 | supertypes 48 | subtypes 49 | rarity 50 | text 51 | flavor 52 | artist 53 | number 54 | power 55 | toughness 56 | loyalty 57 | variations 58 | watermark 59 | border 60 | timeshifted 61 | hand 62 | life 63 | reserved 64 | release_date 65 | starter 66 | rulings 67 | foreign_names 68 | printings 69 | original_text 70 | original_type 71 | legalities 72 | source 73 | image_url 74 | set 75 | set_name 76 | id 77 | 78 | #### Set 79 | 80 | code 81 | name 82 | gatherer_code 83 | old_code 84 | magic_cards_info_code 85 | release_date 86 | border 87 | type 88 | block 89 | online_only 90 | booster 91 | mkm_id 92 | mkm_name 93 | 94 | ### How to get cards from specific language 95 | 96 | #### Languages 97 | Please note that a card may or may not be available in each language listed below. 98 | 99 | Chinese Simplified 100 | Chinese Traditional 101 | French 102 | German 103 | Italian 104 | Japanese 105 | Korean 106 | Portuguese (Brazil) 107 | Russian 108 | Spanish 109 | 110 | Card.where(language="your_language").all() 111 | Example: 112 | card = Card.where(language="Chinese Traditional").all() 113 | 114 | ### Find Card by Multiverse Id 115 | 116 | card = Card.find(386616) 117 | 118 | ### Filter Cards via Query Parameters 119 | 120 | cards = Card.where(set='ktk').where(subtypes='warrior,human').all() 121 | 122 | ### Get all cards (will page through all the data - could take awhile) 123 | 124 | cards = Card.all() 125 | 126 | ### Get all cards, but only a specific page of data 127 | 128 | cards = Card.where(page=5).where(pageSize=1000).all() 129 | 130 | ### Find a Set by code 131 | 132 | set = Set.find('ktk') 133 | 134 | ### Get all sets 135 | 136 | sets = Set.all() 137 | 138 | ### Filter sets via query parameters 139 | 140 | sets = Set.where(name='khans').all() 141 | 142 | ### Get all types 143 | 144 | types = Type.all() 145 | 146 | ### Get all subtypes 147 | 148 | subtypes = Subtype.all() 149 | 150 | ### Get all supertypes 151 | 152 | supertypes = Supertype.all() 153 | 154 | ## Development 155 | 156 | Install the [EditorConfig] plugin for your text editor or IDE 157 | 158 | ### Linux 159 | 160 | 1. Install dependencies: `make setup` 161 | 2. Run test suite: `make test` 162 | 163 | ### Windows 164 | 165 | 1. Install dependencies: `python setup.py install` 166 | 2. Run test suite: `python -m unittest discover tests/` 167 | -------------------------------------------------------------------------------- /mtgsdk/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of mtgsdk. 5 | # https://github.com/MagicTheGathering/mtg-sdk-python 6 | 7 | # Licensed under the MIT license: 8 | # http://www.opensource.org/licenses/MIT-license 9 | # Copyright (c) 2016, Andrew Backes 10 | 11 | from mtgsdk.config import __version__, __pypi_packagename__, __github_username__, __github_reponame__, __endpoint__ 12 | from mtgsdk.card import Card 13 | from mtgsdk.set import Set 14 | from mtgsdk.supertype import Supertype 15 | from mtgsdk.subtype import Subtype 16 | from mtgsdk.type import Type 17 | from mtgsdk.changelog import Changelog 18 | from mtgsdk.restclient import RestClient 19 | from mtgsdk.restclient import MtgException 20 | from mtgsdk.querybuilder import QueryBuilder 21 | -------------------------------------------------------------------------------- /mtgsdk/card.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of mtgsdk. 5 | # https://github.com/MagicTheGathering/mtg-sdk-python 6 | 7 | # Licensed under the MIT license: 8 | # http://www.opensource.org/licenses/MIT-license 9 | # Copyright (c) 2016, Andrew Backes 10 | 11 | from mtgsdk.querybuilder import QueryBuilder 12 | from string import ascii_uppercase, ascii_lowercase 13 | 14 | 15 | class Card(object): 16 | RESOURCE = 'cards' 17 | 18 | """Usual attributes : 19 | artist, border, cmc, color_identity, colors, flavor, foreign_names, hand, 20 | id, image_url, layout, legalities, life, loyalty, mana_cost, multiverse_id, 21 | name, names, number, original_text, original_type, power, printings, rarity, 22 | release_date, rulings, set, set_name, source, starter, subtypes, supertypes, 23 | text, timeshifted, toughness, type, types, variations, watermark. 24 | See online docs for details.""" 25 | 26 | # some keys in the response_dict are of the form fooBarBaz ; 27 | # we want them as foo_bar_baz 28 | trans = str.maketrans({u:"_"+l for u,l in zip(ascii_uppercase, ascii_lowercase)}) 29 | 30 | def __new__(cls, response_dict=dict()) : 31 | obj = object.__new__(__class__) 32 | response_dict = {k.translate(__class__.trans):v for k,v in response_dict.items()} 33 | if "multiverseid" in response_dict.keys() : # one exception, to be fixed in mtgjson ? 34 | response_dict["multiverse_id"] = response_dict.pop("multiverseid") 35 | obj.__dict__ = response_dict 36 | return obj 37 | 38 | @staticmethod 39 | def find(id): 40 | return QueryBuilder(__class__).find(id) 41 | 42 | @staticmethod 43 | def where(**kwargs): 44 | return QueryBuilder(__class__).where(**kwargs) 45 | 46 | @staticmethod 47 | def all(): 48 | """Returns a list of all Card instances""" 49 | return QueryBuilder(__class__).all() 50 | 51 | @staticmethod 52 | def iter(): 53 | """Iterate over all Card instances""" 54 | return QueryBuilder(__class__).iter() 55 | -------------------------------------------------------------------------------- /mtgsdk/changelog.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of mtgsdk. 5 | # https://github.com/MagicTheGathering/mtg-sdk-python 6 | 7 | # Licensed under the MIT license: 8 | # http://www.opensource.org/licenses/MIT-license 9 | # Copyright (c) 2016, Andrew Backes 10 | 11 | from mtgsdk.querybuilder import QueryBuilder 12 | 13 | 14 | class Changelog(object): 15 | RESOURCE = 'changelogs' 16 | 17 | def __init__(self, response_dict={}): 18 | self.id = response_dict.get('id') 19 | self.version = response_dict.get('version') 20 | self.details = response_dict.get('details') 21 | self.release_date = response_dict.get('releaseDate') 22 | 23 | @staticmethod 24 | def all(): 25 | return QueryBuilder(Changelog).all() 26 | -------------------------------------------------------------------------------- /mtgsdk/config.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of mtgsdk. 5 | # https://github.com/MagicTheGathering/mtg-sdk-python 6 | 7 | # Licensed under the MIT license: 8 | # http://www.opensource.org/licenses/MIT-license 9 | # Copyright (c) 2016, Andrew Backes 10 | 11 | __version__ = "1.3.2" 12 | __pypi_packagename__ = "mtgsdk" 13 | __github_username__ = "MagicTheGathering" 14 | __github_reponame__ = "mtg-sdk-python" 15 | __endpoint__ = "https://api.magicthegathering.io/v1" 16 | -------------------------------------------------------------------------------- /mtgsdk/querybuilder.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of mtgsdk. 5 | # https://github.com/MagicTheGathering/mtg-sdk-python 6 | 7 | # Licensed under the MIT license: 8 | # http://www.opensource.org/licenses/MIT-license 9 | # Copyright (c) 2016, Andrew Backes 10 | from mtgsdk.restclient import RestClient 11 | from mtgsdk.config import __endpoint__ 12 | 13 | 14 | class QueryBuilder(object): 15 | def __init__(self, type): 16 | self.params = {} 17 | self.type = type 18 | 19 | def find(self, id): 20 | """Get a resource by its id 21 | 22 | Args: 23 | id (string): Resource id 24 | Returns: 25 | object: Instance of the resource type 26 | """ 27 | url = "{}/{}/{}".format(__endpoint__, self.type.RESOURCE, id) 28 | response = RestClient.get(url)[self.type.RESOURCE[:-1]] 29 | return self.type(response) 30 | 31 | def find_many(self, url, type, resource): 32 | """Get a list of resources 33 | 34 | Args: 35 | url (string): URL to invoke 36 | type (class): Class type 37 | resource (string): The REST Resource 38 | Returns: 39 | list of object: List of resource instances 40 | """ 41 | return [type(item) for item in RestClient.get(url)[resource]] 42 | 43 | def where(self, **kwargs): 44 | """Adds a parameter to the dictionary of query parameters 45 | 46 | Args: 47 | **kwargs: Arbitrary keyword arguments. 48 | Returns: 49 | QueryBuilder: Instance of the QueryBuilder 50 | """ 51 | self.params.update(kwargs) 52 | 53 | return self 54 | 55 | def all(self): 56 | """Get all resources, automatically paging through data 57 | 58 | Returns: 59 | list of object: List of resource objects 60 | """ 61 | 62 | return list(self) # indirect calls of self.__iter__ 63 | 64 | def iter(self): 65 | """Gets all resources, automating paging through data 66 | 67 | Returns: 68 | iterable of object: Iterable of resource objects 69 | """ 70 | 71 | page = 1 72 | fetch_all = True 73 | url = "{}/{}".format(__endpoint__, self.type.RESOURCE) 74 | 75 | if 'page' in self.params: 76 | page = self.params['page'] 77 | fetch_all = False 78 | 79 | response = RestClient.get(url, self.params)[self.type.RESOURCE] 80 | while len(response): 81 | for item in response: 82 | yield self.type(item) 83 | 84 | if not fetch_all: 85 | break 86 | else: 87 | page += 1 88 | self.where(page=page) 89 | response = RestClient.get(url, self.params)[self.type.RESOURCE] 90 | 91 | __iter__ = iter 92 | 93 | def array(self): 94 | """Get all resources and return the result as an array 95 | 96 | Returns: 97 | array of str: Array of resources 98 | """ 99 | url = "{}/{}".format(__endpoint__, self.type.RESOURCE) 100 | return RestClient.get(url, self.params)[self.type.RESOURCE] 101 | -------------------------------------------------------------------------------- /mtgsdk/restclient.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of mtgsdk. 5 | # https://github.com/MagicTheGathering/mtg-sdk-python 6 | 7 | # Licensed under the MIT license: 8 | # http://www.opensource.org/licenses/MIT-license 9 | # Copyright (c) 2016, Andrew Backes 10 | 11 | import json 12 | from urllib.request import Request, urlopen 13 | from urllib.error import HTTPError 14 | from urllib.parse import urlencode 15 | 16 | 17 | class RestClient(object): 18 | 19 | @staticmethod 20 | def get(url, params={}): 21 | """Invoke an HTTP GET request on a url 22 | 23 | Args: 24 | url (string): URL endpoint to request 25 | params (dict): Dictionary of url parameters 26 | Returns: 27 | dict: JSON response as a dictionary 28 | """ 29 | request_url = url 30 | 31 | if len(params): 32 | request_url = "{}?{}".format(url, urlencode(params)) 33 | 34 | try: 35 | req = Request(request_url, headers={'User-Agent': 'Mozilla/5.0'}) 36 | response = json.loads(urlopen(req).read().decode("utf-8")) 37 | 38 | return response 39 | except HTTPError as err: 40 | raise MtgException(err.read()) 41 | 42 | 43 | class MtgException(Exception): 44 | def __init__(self, description): 45 | self.description = description 46 | 47 | def __str__(self): 48 | return self.description 49 | -------------------------------------------------------------------------------- /mtgsdk/set.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of mtgsdk. 5 | # https://github.com/MagicTheGathering/mtg-sdk-python 6 | 7 | # Licensed under the MIT license: 8 | # http://www.opensource.org/licenses/MIT-license 9 | # Copyright (c) 2016, Andrew Backes 10 | 11 | from mtgsdk.querybuilder import QueryBuilder 12 | from mtgsdk.config import __endpoint__ 13 | from mtgsdk.card import Card 14 | from string import ascii_uppercase, ascii_lowercase 15 | 16 | 17 | class Set(object): 18 | RESOURCE = 'sets' 19 | 20 | """Usual attributes : 21 | block, booster, border, code, gatherer_code, magic_cards_info_code, mkm_id, 22 | mkm_name, name, old_code, online_only, release_date, type. 23 | See online docs for details.""" 24 | 25 | # some keys in the response_dict are of the form fooBarBaz ; 26 | # we want them as foo_ 27 | trans = str.maketrans({u:"_"+l for u,l in zip(ascii_uppercase, ascii_lowercase)}) 28 | 29 | def __new__(cls, response_dict=dict()) : 30 | obj = object.__new__(__class__) 31 | obj.__dict__ = {k.translate(__class__.trans):v for k,v in response_dict.items()} 32 | return obj 33 | 34 | @staticmethod 35 | def find(id): 36 | return QueryBuilder(__class__).find(id) 37 | 38 | @staticmethod 39 | def where(**kwargs): 40 | return QueryBuilder(__class__).where(**kwargs) 41 | 42 | @staticmethod 43 | def all(): 44 | return QueryBuilder(__class__).all() 45 | 46 | @staticmethod 47 | def generate_booster(code): 48 | url = "{}/{}/{}/booster".format(__endpoint__, Set.RESOURCE, code) 49 | return QueryBuilder(Set).find_many(url, Card, Card.RESOURCE) 50 | -------------------------------------------------------------------------------- /mtgsdk/subtype.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of mtgsdk. 5 | # https://github.com/MagicTheGathering/mtg-sdk-python 6 | 7 | # Licensed under the MIT license: 8 | # http://www.opensource.org/licenses/MIT-license 9 | # Copyright (c) 2016, Andrew Backes 10 | 11 | from mtgsdk.querybuilder import QueryBuilder 12 | 13 | 14 | class Subtype(object): 15 | RESOURCE = 'subtypes' 16 | 17 | @staticmethod 18 | def all(): 19 | return QueryBuilder(__class__).array() 20 | -------------------------------------------------------------------------------- /mtgsdk/supertype.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of mtgsdk. 5 | # https://github.com/MagicTheGathering/mtg-sdk-python 6 | 7 | # Licensed under the MIT license: 8 | # http://www.opensource.org/licenses/MIT-license 9 | # Copyright (c) 2016, Andrew Backes 10 | 11 | from mtgsdk.querybuilder import QueryBuilder 12 | 13 | 14 | class Supertype(object): 15 | RESOURCE = 'supertypes' 16 | 17 | @staticmethod 18 | def all(): 19 | return QueryBuilder(__class__).array() 20 | -------------------------------------------------------------------------------- /mtgsdk/type.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of mtgsdk. 5 | # https://github.com/MagicTheGathering/mtg-sdk-python 6 | 7 | # Licensed under the MIT license: 8 | # http://www.opensource.org/licenses/MIT-license 9 | # Copyright (c) 2016, Andrew Backes 10 | 11 | from mtgsdk.querybuilder import QueryBuilder 12 | 13 | 14 | class Type(object): 15 | RESOURCE = 'types' 16 | 17 | @staticmethod 18 | def all(): 19 | return QueryBuilder(__class__).array() 20 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | description-file = README.md 3 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of mtgsdk. 5 | # https://github.com/MagicTheGathering/mtg-sdk-python 6 | 7 | # Licensed under the MIT license: 8 | # http://www.opensource.org/licenses/MIT-license 9 | # Copyright (c) 2016, Andrew Backes 10 | 11 | import sys, os 12 | from setuptools import setup, find_packages 13 | sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'mtgsdk')) 14 | from config import __version__, __pypi_packagename__, __github_username__, __github_reponame__ 15 | 16 | tests_require = [ 17 | 'mock', 18 | 'nose', 19 | 'coverage', 20 | 'yanc', 21 | 'preggy', 22 | 'tox', 23 | 'ipdb', 24 | 'coveralls', 25 | 'sphinx', 26 | 'vcrpy' 27 | ] 28 | 29 | url='https://github.com/' + __github_username__ + '/' + __github_reponame__ 30 | download_url="{}/tarball/{}".format(url, __version__) 31 | 32 | setup( 33 | name=__pypi_packagename__, 34 | version=__version__, 35 | description='Magic: The Gathering SDK for magicthegathering.io', 36 | long_description=''' 37 | Magic: The Gathering SDK is a python wrapper around the MTG API located at magicthegathering.io 38 | ''', 39 | keywords='mtg sdk magic gathering gatherer api rest', 40 | author='Andrew Backes', 41 | author_email='backes.andrew@gmail.com', 42 | url=url, 43 | download_url=download_url, 44 | license='MIT', 45 | classifiers=[ 46 | 'Development Status :: 4 - Beta', 47 | 'Intended Audience :: Developers', 48 | 'License :: OSI Approved :: MIT License', 49 | 'Natural Language :: English', 50 | 'Operating System :: Unix', 51 | 'Programming Language :: Python :: 3.4', 52 | 'Operating System :: OS Independent', 53 | ], 54 | packages=find_packages(), 55 | include_package_data=False, 56 | install_requires=[ 57 | # add your dependencies here 58 | # remember to use 'package-name>=x.y.z, 10 | -------------------------------------------------------------------------------- /tests/test_card.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of mtgsdk. 5 | # https://github.com/MagicTheGathering/mtg-sdk-python 6 | 7 | # Licensed under the MIT license: 8 | # http://www.opensource.org/licenses/MIT-license 9 | # Copyright (c) 2016, Andrew Backes 10 | 11 | import vcr 12 | import unittest 13 | from mtgsdk import Card 14 | 15 | # Python 3.6 Workaround until https://github.com/kevin1024/vcrpy/issues/293 is fixed. 16 | vcr_connection_request = vcr.stubs.VCRConnection.request 17 | vcr.stubs.VCRConnection.request = lambda *args, **kwargs: vcr_connection_request(*args) 18 | 19 | class TestCard(unittest.TestCase): 20 | def test_find_returns_card(self): 21 | with vcr.use_cassette('fixtures/choice_of_damnations.yaml'): 22 | card = Card.find(88803) 23 | 24 | self.assertEqual('Choice of Damnations', card.name) 25 | self.assertEqual('{5}{B}', card.mana_cost) 26 | self.assertEqual(6, card.cmc) 27 | self.assertEqual('Sorcery — Arcane', card.type) 28 | self.assertTrue('Black' in card.colors) 29 | self.assertEqual(['B'], card.color_identity) 30 | self.assertTrue('Sorcery' in card.types) 31 | self.assertTrue('Arcane' in card.subtypes) 32 | self.assertEqual('Rare', card.rarity) 33 | self.assertEqual('SOK', card.set) 34 | self.assertEqual('Saviors of Kamigawa', card.set_name) 35 | self.assertEqual("Target opponent chooses a number. You may have that player lose that much life. If you don't, that player sacrifices all but that many permanents.", card.text) 36 | self.assertEqual("\"Life is a series of choices between bad and worse.\" —Toshiro Umezawa", card.flavor) 37 | self.assertEqual('Tim Hildebrandt', card.artist) 38 | self.assertEqual('62', card.number) 39 | self.assertEqual(88803, card.multiverse_id) 40 | self.assertEqual('http://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=88803&type=card', card.image_url) 41 | self.assertTrue(len(card.rulings) > 0) 42 | self.assertTrue({"name":"Scelta della Dannazione","text" : "L'avversario bersaglio sceglie un numero. Puoi far perdere a quel giocatore un ammontare di punti vita pari a quel numero. Se non lo fai, quel giocatore sacrifica tutti i permanenti tranne un numero di permanenti pari al numero scelto.","flavor" : "\"La vita è una sequela di scelte tra male e peggio.\"\n—Toshiro Umezawa","imageUrl":"http://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=105393&type=card","language":"Italian","multiverseid":105393} in card.foreign_names) 43 | self.assertTrue('SOK' in card.printings) 44 | self.assertEqual("Target opponent chooses a number. You may have that player lose that much life. If you don't, that player sacrifices all but that many permanents.", card.original_text) 45 | self.assertEqual('Sorcery - Arcane', card.original_type) 46 | self.assertTrue({"format":"Commander","legality":"Legal"} in card.legalities) 47 | self.assertEqual('224a2a63-7be6-5e06-bf6b-e667727bf80b', card.id) 48 | 49 | def test_all_with_params_return_cards(self): 50 | with vcr.use_cassette('fixtures/legendary_elf_warriors.yaml'): 51 | cards = Card.where(supertypes='legendary') \ 52 | .where(subtypes='elf,warrior') \ 53 | .all() 54 | 55 | self.assertTrue(len(cards) >= 13) 56 | 57 | def test_all_with_page_returns_cards(self): 58 | with vcr.use_cassette('fixtures/all_first_page.yaml'): 59 | cards = Card.where(page=1).all() 60 | 61 | self.assertEqual(100, len(cards)) 62 | 63 | def test_all_with_page_and_page_size_returns_card(self): 64 | with vcr.use_cassette('fixtures/all_first_page_one_card.yaml'): 65 | cards = Card.where(page=1).where(pageSize=1).all() 66 | 67 | self.assertEqual(1, len(cards)) 68 | 69 | def test_iter_with_no_where_returns_card(self): 70 | with vcr.use_cassette('fixtures/cards_no_args.yaml'): 71 | card = next(Card.iter()) 72 | self.assertIsInstance(card, Card) 73 | -------------------------------------------------------------------------------- /tests/test_changelog.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of mtgsdk. 5 | # https://github.com/MagicTheGathering/mtg-sdk-python 6 | 7 | # Licensed under the MIT license: 8 | # http://www.opensource.org/licenses/MIT-license 9 | # Copyright (c) 2016, Andrew Backes 10 | 11 | import vcr 12 | import unittest 13 | from mtgsdk import Changelog 14 | 15 | class TestChangelog(unittest.TestCase): 16 | def test_all_returns_changelogs(self): 17 | with vcr.use_cassette('fixtures/changelogs.yaml'): 18 | changelogs = Changelog.all() 19 | 20 | #self.assertTrue(len(changelogs) > 1) 21 | self.assertTrue(len(changelogs) == 0) -------------------------------------------------------------------------------- /tests/test_config.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of mtgsdk. 5 | # https://github.com/MagicTheGathering/mtg-sdk-python 6 | 7 | # Licensed under the MIT license: 8 | # http://www.opensource.org/licenses/MIT-license 9 | # Copyright (c) 2016, Andrew Backes 10 | 11 | import unittest 12 | from mtgsdk import __version__, __pypi_packagename__, __github_username__, __github_reponame__, __endpoint__ 13 | 14 | class TestConfig(unittest.TestCase): 15 | def test_has_proper_version(self): 16 | self.assertEqual('1.3.2', __version__) 17 | 18 | def test_has_proper_packagename(self): 19 | self.assertEqual('mtgsdk', __pypi_packagename__) 20 | 21 | def test_has_proper_github_username(self): 22 | self.assertEqual('MagicTheGathering', __github_username__) 23 | 24 | def test_has_proper_github_reponame(self): 25 | self.assertEqual('mtg-sdk-python', __github_reponame__) 26 | 27 | def test_has_proper_endpoint(self): 28 | self.assertEqual('https://api.magicthegathering.io/v1', __endpoint__) 29 | -------------------------------------------------------------------------------- /tests/test_mtgexception.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of mtgsdk. 5 | # https://github.com/MagicTheGathering/mtg-sdk-python 6 | 7 | # Licensed under the MIT license: 8 | # http://www.opensource.org/licenses/MIT-license 9 | # Copyright (c) 2016, Andrew Backes 10 | 11 | import unittest 12 | from mtgsdk import MtgException 13 | 14 | class TestMtgException(unittest.TestCase): 15 | def test_constructor_sets_description(self): 16 | description = "An error has occurred" 17 | exception = MtgException(description) 18 | 19 | self.assertEqual(description, exception.__str__()) 20 | -------------------------------------------------------------------------------- /tests/test_set.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of mtgsdk. 5 | # https://github.com/MagicTheGathering/mtg-sdk-python 6 | 7 | # Licensed under the MIT license: 8 | # http://www.opensource.org/licenses/MIT-license 9 | # Copyright (c) 2016, Andrew Backes 10 | 11 | import vcr 12 | import unittest 13 | from mtgsdk import Set 14 | 15 | class TestSet(unittest.TestCase): 16 | def test_find_returns_set(self): 17 | with vcr.use_cassette('fixtures/ktk.yaml'): 18 | set = Set.find('ktk') 19 | 20 | self.assertEqual('KTK', set.code) 21 | self.assertEqual('Khans of Tarkir', set.name) 22 | self.assertEqual('expansion', set.type) 23 | #NOTE: The API doesn't seem to be providing "border" at this time 24 | #self.assertEqual('black', set.border) 25 | self.assertTrue('common' in set.booster) 26 | self.assertEqual('2014-09-26', set.release_date) 27 | #NOTE: The API doesn't seem to be providing "magic_cards_info_code at this time 28 | #self.assertEqual('ktk', set.magic_cards_info_code) 29 | 30 | def test_generate_booster_returns_cards(self): 31 | with vcr.use_cassette('fixtures/booster.yaml'): 32 | cards = Set.generate_booster('ktk') 33 | 34 | #NOTE: API booster size seems incorrect, returns 14 cards instead of expected 15 35 | self.assertEqual(14, len(cards)) 36 | 37 | self.assertEqual('KTK', cards[0].set) 38 | 39 | def test_where_filters_on_name(self): 40 | with vcr.use_cassette('fixtures/filtered_sets.yaml'): 41 | sets = Set.where(name='khans of tarkir promos').all() 42 | 43 | self.assertEqual(1, len(sets)) 44 | self.assertEqual('PKTK', sets[0].code) 45 | 46 | def test_all_returns_all_sets(self): 47 | with vcr.use_cassette('fixtures/all_sets.yaml'): 48 | sets = Set.all() 49 | 50 | self.assertGreater(len(sets), 190) 51 | -------------------------------------------------------------------------------- /tests/test_subtype.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of mtgsdk. 5 | # https://github.com/MagicTheGathering/mtg-sdk-python 6 | 7 | # Licensed under the MIT license: 8 | # http://www.opensource.org/licenses/MIT-license 9 | # Copyright (c) 2016, Andrew Backes 10 | 11 | import vcr 12 | import unittest 13 | from mtgsdk import Subtype 14 | 15 | class TestSubtype(unittest.TestCase): 16 | def test_all_returns_subtypes(self): 17 | with vcr.use_cassette('fixtures/subtypes.yaml'): 18 | subtypes = Subtype.all() 19 | 20 | self.assertTrue(len(subtypes) > 20) 21 | self.assertTrue('Warrior' in subtypes) 22 | -------------------------------------------------------------------------------- /tests/test_supertype.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of mtgsdk. 5 | # https://github.com/MagicTheGathering/mtg-sdk-python 6 | 7 | # Licensed under the MIT license: 8 | # http://www.opensource.org/licenses/MIT-license 9 | # Copyright (c) 2016, Andrew Backes 10 | 11 | import vcr 12 | import unittest 13 | from mtgsdk import Supertype 14 | 15 | class TestSupertype(unittest.TestCase): 16 | def test_all_returns_supertypes(self): 17 | with vcr.use_cassette('fixtures/supertypes.yaml'): 18 | supertypes = Supertype.all() 19 | 20 | #API currently misplaces Host among Supertypes instead of regular types, remove Host when API is updated 21 | self.assertEqual(["Basic","Host","Legendary","Ongoing","Snow","World"], supertypes) 22 | -------------------------------------------------------------------------------- /tests/test_type.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of mtgsdk. 5 | # https://github.com/MagicTheGathering/mtg-sdk-python 6 | 7 | # Licensed under the MIT license: 8 | # http://www.opensource.org/licenses/MIT-license 9 | # Copyright (c) 2016, Andrew Backes 10 | 11 | import vcr 12 | import unittest 13 | from mtgsdk import Type 14 | 15 | class TestType(unittest.TestCase): 16 | def test_all_returns_types(self): 17 | with vcr.use_cassette('fixtures/types.yaml'): 18 | types = Type.all() 19 | 20 | #API returns some erroneous values, but this line is correct 21 | #Remove temporary line and uncomment this line when API is updated 22 | # self.assertEqual(["Artifact","Card","Conspiracy","Creature","Emblem","Enchantment","Host","Instant","Land","Phenomenon","Plane","Planeswalker","Scheme","Sorcery","Summon","Tribal","Vanguard","You'll"], types) 23 | self.assertEqual(["Artifact","Conspiracy","Creature","Enchantment","Hero","instant","Instant","Land","Phenomenon","Plane","Planeswalker","Scheme","Sorcery","Summon","Tribal","Vanguard","You’ll"], types) 24 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | # This file is part of mtgsdk. 2 | # https://github.com/MagicTheGathering/mtg-sdk-python 3 | 4 | # Licensed under the MIT license: 5 | # http://www.opensource.org/licenses/MIT-license 6 | # Copyright (c) 2016, Andrew Backes 7 | 8 | [tox] 9 | envlist = py34 10 | 11 | [testenv] 12 | commands = 13 | make setup 14 | make test 15 | --------------------------------------------------------------------------------