Skip to main content

ESY is an ESI wrapper aiming to be simple and pythonic.

Project description

Introduction

Build Status Coverage Status Documentation Status

There are many options for consuming the ESI web services. ESY aims to be an easy-to-use library with the nuts and bolts of dealing with an OpenAPI interface abstracted away.

ESY is inspired by Entity's gloriously pythonic eveapi library.

Installation

The latest stable version of ESY is available from PyPI:

$ pip install esy

Documentation

Documentation is available at esy.readthedocs.io.

For documentation of the various ESI routes, ESY also provides a terse list of their parameters and return types. Further information can be explored at the main ESI documentation site

Usage

ESY comes with two interfaces to ESI:

  • An interface generated by Bravado, with some added sugar for dealing with pagination.
  • A semantic wrapper generated through pythonic voodoo.

The two interfaces caters different needs. The Bravado interface is an OpenAPI wrapper around the ESI that will be familiar for most developers familiar working with swagger. The semantic wrapper, on the other hand, generates classes for various entities in ESI like Character, Corporation and Alliance. Neither interface is mutual exclusive and for many use cases, it makes sense using both.

Regardless of interface, to use ESY, you must first initialize a client:

from esy.client import ESIClient
client = ESIClient.get_client(user_agent='my-user-agent')

The client can take a second or two to initialize, as the swagger specification is downloaded and parsed. To speed this up, you can download the specification locally:

$ curl https://esi.evetech.net/latest/swagger.json -o swagger.json

Then initialize the client using the local file:

import json
from esy.client import ESIClient

with open('swagger.json', 'r') as spec_file:
    spec = json.load(spec_file)
client = ESIClient.get_client('my-user-agent', spec=spec)

For production instances, keeping the spec in Redis or some other cache is highly recommended.

Pagination

For ESI routes which are paginated, ESY will return a ESIPageGenerator which is a generator yielding the native data type of the route.

Using the semantic wrapper

from esy.entities import Character, Corporation, Alliance, Entity


# You can initialize entities using their IDs
vittoros = Character(941287462)
evolution = Corporation(144749962)
ccp = Alliance(434243723)


# To speed up initialization, it's recommended to create and share an ESIClient among instances. If no client is 
# supplied, a new one will be created for each entity instance.
from esy.client import ESIClient
client = ESIClient.get_client(user_agent='my-user-agent')

vittoros = Character(941287462, _client=client)

# You can also initialize instances just using the entity names

vittoros = Character.from_name('Vittoros', _client=client)
evolution = Corporation.from_name('Evolution', _client=client)

# or speed things up by initializing many entites at the same time

entities = Entity.from_names('Vittoros', 'Evolution', 'Northern Coalition.', _client=client)
print(entities)

{'Northern Coalition.': <esy.entities.Alliance object at 0x0000023967F10860>, 
 'Vittoros': <esy.entities.Character object at 0x0000023967F10BE0>, 
 'Evolution': <esy.entities.Corporation object at 0x0000023967F10B70>}

Any initialized entity will allow you to access the various public information. To access the private services, you need to supply an authorization token first.

vittoros = Character.from_name('Vittoros', _client=client, _token='hunter2')

# or you can set the token after initialization

vittoros.set_token('hunter2')

After this, you can access all the private services:

for asset_page in vittoros.get_assets():
    print(asset_page)

for contract_page in vittoros.get_contracts():
    for contract in contract_page:
        for bid in vittoros.get_contracts_contract_bids(contract_id=contract.get('contract_id')):
            print(bid.get('bidder_id'), bid.get('amount'), bid.get('date_bid'))

Check out the entities API for a more extensive list of available services.

Using the Bravado interface

The Bravado interface is available from the ESIClient instance.

from esy.client import ESIClient
client = ESIClient.get_client(user_agent='my-user-agent')

# Get list of alliances
alliances = client.Alliance.get_alliances()

# Get info on a corporation
evolution = client.Corporation.get_corporations_corporation_id(corporation_id=144749962)
print(evolution)

{'alliance_id': 1727758877, 
 'ceo_id': 144509256, 
 'creator_id': 144509256, 
 'date_founded': datetime.datetime(2003, 7, 30, 8, 33, tzinfo=tzutc()), 
 'description': 'Those who cannot adapt become victims of Evolution.', 
 'home_station_id': 60013843, 
 'member_count': 316, 
 'name': 'Evolution', 
 'shares': 1000, 
 'tax_rate': 0.5, 
 'ticker': 'EVOL', 
 'url': 'http://www.eve-evol.com', 
 'faction_id': None}
# Get paginated asset list
swag =  client.Corporation.get_corporations_corporation_id_assets(corporation_id=144749962,
                                                                  _token='esi token')
# swag is an ESIPageGenerator, implementing the generator interface
# Loop through it to get the asset pages
for page in swag:  # Returns a list of assets
    for asset in page:  # Asset dict 
       print(asset.get('type_id'),
             asset.get('location_id'))
       # 22457
       # 16074150552

Caching

ESY does not implement caching itself, but supports using a cache through a cache proxy object. The proxy needs to implement the following interface:

class Cache(object):    
    def get(self, key: int) -> object: 
        pass

    def set(self, key: int, data: object, cached_until: datetime.datetime):
        pass

    def __contains__(self, item: object) -> bool:
        pass

Authentication and devel mode

ESY can handle the authentication flow for you:

from esy.auth import ESIAuthenticator

auth = ESIAuthenticator()
refresh_token, access_token = auth.verify_authorization_code('authorization code from esi',
                                                             'your client ID',
                                                             'your secret key')

auth.verify_access_token(access_token)
{'CharacterID': 941287462,
 'CharacterName': 'Vittoros',
 'ExpiresOn': '2018-06-11T19:01:15.182864Z',
 'Scopes': ' ',
 'TokenType': 'Character',
 'CharacterOwnerHash': '**********'}

new_access_token = auth.get_access_token(refresh_token, 
                                         'your client ID', 
                                         'your secret key')

auth.revoke_token(refresh_token,
                  'your client ID', 
                  'your secret key')

auth.revoke_token(access_token,
                  'your client ID', 
                  'your secret key',
                  token_type='access_token')

To help developers getting started without having to implement the entire authentication workflow, ESY also implements an ad-hoc web server to get you refresh tokens. You can use it directly in the python prompt to do some API exploration or you can use it in your tests to produce refresh or access tokens for testing your ESI calls.

First, create a new application at https://developers.eveonline.com/ with callback URL set to http://localhost:8000 or whichever address and port you'll be running the devel server.

import esy.devel

# get_authorization_code has many parameters, but for basic usage:

auth_code = esy.devel.get_authorization_code(client_id='your client ID',
                                             callback_url='your callback URL', 
                                             scopes='your space-delimited scopes')

# This will start the web server in the background (per-default listening on localhost:8000)
# and print the login URL on stdout. After authenticating in your browser, the web server 
# will get redirect from the SSO with the authorization code, then return that.

# For situations where you are not able to reach the network where you are running ESY, 
# you can also use CLI login: 

auth_code = esy.devel.get_authorization_code(cli_login=True,
                                             client_id='your client ID',
                                             callback_url='your callback URL', 
                                             scopes='your space-delimited scopes')

# This will prompt for username and password, then let you pick a character.
# If you are running tests, you can also supply username, password and character_id as 
# keyword arguments to get_authorization_code, in addition to cli_login=True. This will
# automate the entire flow. Remember to revoke your tokens afterwards and for bob's sake; 
# don't display your username and/or password!

# After getting the authorization code, you can get the tokens:

refresh_token, access_token = esy.devel.verify_authorization_code(auth_code,
                                                                  client_id='your client ID',
                                                                  secret_key='your secret key')
# Character info

char_info = esy.devel.verify_access_token(access_token)

# Get your swag
from esy.client import ESIClient
client = ESIClient.get_client(user_agent='your-user-agent')
assets = client.Assets.get_characters_character_id_assets(
    character_id=char_info.get('CharacterId'), _token=access_token)

for page in assets:
    print(page)

The devel mode will use parameters from environment settings, if present:

Parameter Environment setting Default
CLIENT_ID ESY_CLIENT_ID None
SECRET_KEY ESY_SECRET_KEY None
SCOPES ESY_SCOPES None
CALLBACK_URL ESY_CALLBACK_URL http://localhost:8000
SERVER_ADDRESS ESY_SERVER_ADDRESS localhost
SERVER_PORT ESY_SERVER_PORT 8000

Development

ESY uses the Bravado OpenAPI library to parse the ESI swagger schema and create an usable interface. The purpose of creating a custom wrapper of Bravado for ESI, is to make the interface a bit more user friendly. Pagination is handled automatically by returning generators for any route which accepts a page parameter, while non-paginated data is handled in their native data type. Tokens can be set per-call, instead of per-client, allowing for using headers and still getting data for many tokens without the ned to reinitialize the client.

The authentication flow uses requests-oauthlib.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

esy-1.2.0.tar.gz (18.0 kB view details)

Uploaded Source

Built Distribution

esy-1.2.0-py2.py3-none-any.whl (15.3 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file esy-1.2.0.tar.gz.

File metadata

  • Download URL: esy-1.2.0.tar.gz
  • Upload date:
  • Size: 18.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.11.0 pkginfo/1.4.2 requests/2.19.1 setuptools/40.0.0 requests-toolbelt/0.8.0 tqdm/4.23.4 CPython/3.6.2

File hashes

Hashes for esy-1.2.0.tar.gz
Algorithm Hash digest
SHA256 5f0d992ca1f042d80074d084eb6d6f68aec1ae7c608738078d8d83e1c2ab23c8
MD5 7cbd30afc74cdd5978366e3811584885
BLAKE2b-256 35432f1eb1680bf206e038bde701139bc756b10b62410be5c0ce03c1f030cc84

See more details on using hashes here.

File details

Details for the file esy-1.2.0-py2.py3-none-any.whl.

File metadata

  • Download URL: esy-1.2.0-py2.py3-none-any.whl
  • Upload date:
  • Size: 15.3 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.11.0 pkginfo/1.4.2 requests/2.19.1 setuptools/40.0.0 requests-toolbelt/0.8.0 tqdm/4.23.4 CPython/3.6.2

File hashes

Hashes for esy-1.2.0-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 00d3e079e6c21b282ffa6e83632d804ceefe8649beee96f0b02de3d45b276a40
MD5 1d8bb531c2ea57a886436818cca9e5b8
BLAKE2b-256 5f543435b25c836394b83b458128699689d62f5b505fc128998b0f1e695cc165

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page