Coder Social home page Coder Social logo

josuebrunel / myql Goto Github PK

View Code? Open in Web Editor NEW
31.0 8.0 8.0 1.31 MB

mYQL is a Python wrapper of the Yahoo! Query Language a.k.a YQL (Finances, ...)

Home Page: https://myql.readthedocs.org/en/latest/

License: MIT License

Python 97.36% Shell 1.84% JavaScript 0.80%
python oauth oauth2 yahoo yql

myql's Introduction

Build Status Documentation Status Code Health PyPI PyPI PyPI PyPI PyPI Coverage Status PyPI

mYQL is a Python wrapper of the Yahoo Query Language.

Yahoo! Query Language Documentation and Support

Features

  • Simple YQL Query
  • Authenticated YQL Query ( OAuth )
  • StockScraper
  • YQL Open Table (Classes and Metaclasses) Generator
  • Response prettyfier

Installation

$ pip install myql

Quick Start

It's important to know that response is a just requests.models.Response object. Yes indeed, mYQL uses requests ๐Ÿ˜„

By default, you have access to the community tables. If for whatsoever reason you would like to not have access to those tables

>>> import myql
>>> yql = myql.MYQL(community=False)

####Changing response format (xml or json)

The response format is by default json.

>>> import myql
>>> from myql.utils import pretty_json, pretty_xml
>>> yql = myql.MYQL(format='xml', community=True)
>>> resp = yql.raw_query('select name, woeid from geo.states where place="Congo"')
>>> print(pretty_xml(resp.content))
<?xml version="1.0" encoding="utf-8"?>
<query xmlns:yahoo="http://www.yahooapis.com/v1/base.rng" yahoo:count="11" yahoo:created="2015-06-07T11:56:11Z" yahoo:lang="en-US">
    <results>
        <place xmlns="http://where.yahooapis.com/v1/schema.rng">
            <name>Cuvette-Ouest Department</name>
            <woeid>55998384</woeid>
        </place>
        <place xmlns="http://where.yahooapis.com/v1/schema.rng">
            <name>Cuvette Department</name>
            <woeid>2344968</woeid>
        </place>
        <place xmlns="http://where.yahooapis.com/v1/schema.rng">
            <name>Plateaux District</name>
            <woeid>2344973</woeid>
        </place>
        <place xmlns="http://where.yahooapis.com/v1/schema.rng">
            <name>Sangha</name>
            <woeid>2344974</woeid>
        </place>
        <place xmlns="http://where.yahooapis.com/v1/schema.rng">
            <name>Lekoumou</name>
            <woeid>2344970</woeid>
        </place>
        <place xmlns="http://where.yahooapis.com/v1/schema.rng">
            <name>Pool Department</name>
            <woeid>2344975</woeid>
        </place>
        <place xmlns="http://where.yahooapis.com/v1/schema.rng">
            <name>Likouala Department</name>
            <woeid>2344971</woeid>
        </place>
        <place xmlns="http://where.yahooapis.com/v1/schema.rng">
            <name>Niari Department</name>
            <woeid>2344972</woeid>
        </place>
        <place xmlns="http://where.yahooapis.com/v1/schema.rng">
            <name>Brazzaville</name>
            <woeid>2344976</woeid>
        </place>
        <place xmlns="http://where.yahooapis.com/v1/schema.rng">
            <name>Bouenza Department</name>
            <woeid>2344967</woeid>
        </place>
        <place xmlns="http://where.yahooapis.com/v1/schema.rng">
            <name>Kouilou</name>
            <woeid>2344969</woeid>
        </place>
    </results>
</query>
<!-- total: 33 -->
<!-- pprd1-node1003-lh3.manhattan.bf1.yahoo.com -->

>>> resp = yql.raw_query('select name, woeid from geo.states where place="Congo"', format='json')
>>> print(pretty_json(resp.content))
{
    "query": {
        "count": 11, 
        "created": "2015-06-07T11:58:20Z", 
        "lang": "en-US", 
        "results": {
            "place": [
                {
                    "name": "Cuvette-Ouest Department", 
                    "woeid": "55998384"
                }, 
                {
                    "name": "Cuvette Department", 
                    "woeid": "2344968"
                }, 
                {
                    "name": "Plateaux District", 
                    "woeid": "2344973"
                }, 
                {
                    "name": "Sangha", 
                    "woeid": "2344974"
                }, 
                {
                    "name": "Lekoumou", 
                    "woeid": "2344970"
                }, 
                {
                    "name": "Pool Department", 
                    "woeid": "2344975"
                }, 
                {
                    "name": "Likouala Department", 
                    "woeid": "2344971"
                }, 
                {
                    "name": "Niari Department", 
                    "woeid": "2344972"
                }, 
                {
                    "name": "Brazzaville", 
                    "woeid": "2344976"
                }, 
                {
                    "name": "Bouenza Department", 
                    "woeid": "2344967"
                }, 
                {
                    "name": "Kouilou", 
                    "woeid": "2344969"
                }
            ]
        }
    }
}

>>>

Methods

####use(yql_table_url,name=yql_table_name) Maps a table name to the URL of an Open Data Table.

>>> yql.use('http://www.josuebrunel.org//users.xml', name='myusers') 

####desc(tablename) Returns table description

>>> response = yql.desc('weather.forecast')
>>> print(pretty_json(response.content))
{
    "query": {
        "count": 1, 
        "created": "2015-06-07T12:00:27Z", 
        "lang": "en-US", 
        "results": {
            "table": {
                "hash": "aae78b1462a6a8fbc748aec4cf292767", 
                "meta": {
                    "author": "Yahoo! Inc", 
                    "description": "Weather forecast table", 
                    "documentationURL": "http://developer.yahoo.com/weather/", 
                    "sampleQuery": "select * from weather.forecast where woeid=2502265"
                }, 
                "name": "weather.forecast", 
                "request": {
                    "select": [
                        {
                            "key": [
                                {
                                    "name": "location", 
                                    "required": "true", 
                                    "type": "xs:string"
                                }, 
                                {
                                    "name": "u", 
                                    "type": "xs:string"
                                }
                            ]
                        }, 
                        {
                            "key": [
                                {
                                    "name": "woeid", 
                                    "required": "true", 
                                    "type": "xs:string"
                                }, 
                                {
                                    "name": "u", 
                                    "type": "xs:string"
                                }
                            ]
                        }
                    ]
                }, 
                "security": "ANY"
            }
        }
    }
}

>>>

####raw_query(query)

Allows you to directly type your query

>>> response = yql.raw_query("select * from geo.countries where place='North America'")
>>> # deal with the response

####select(table, fields, limit).where(filters, ...)

NB : A simple select doesn't return any data. Use GET instead.

>>> response = yql.select('geo.countries', ['name', 'code', 'woeid']).where(['name', '=', 'Canada'])
>>> print(pretty_json(response.content))
{
    "query": {
        "count": 1, 
        "created": "2015-06-07T12:10:39Z", 
        "lang": "en-US", 
        "results": {
            "place": {
                "name": "Canada", 
                "woeid": "23424775"
            }
        }
    }
}

>>> ...
>>> response = yql.select('geo.countries', ['name', 'woeid'], 2).where(['place', 'in', ('Africa', 'Europe')])
>>> from myql.utils import dump
>>> dump(response)
{
    "query": {
        "count": 2, 
        "created": "2015-06-07T12:27:04Z", 
        "lang": "en-US", 
        "results": {
            "place": [
                {
                    "name": "Algeria", 
                    "woeid": "23424740"
                }, 
                {
                    "name": "Angola", 
                    "woeid": "23424745"
                }
            ]
        }
    }
}

>>>

####get(table, fields, limit) Same as SELECT, but instead returns data.

REMINDER : Some tables require a where clause, therefore GET won't work on those tables, use select(...).where(...) instead .

>>> from myql.utils import dump
>>> response = yql.get('geo.countries', ['name', 'woeid'], 1)
>>> dump(response)
{
    "query": {
        "count": 1, 
        "created": "2015-06-07T12:29:01Z", 
        "lang": "en-US", 
        "results": {
            "place": {
                "name": "Sao Tome and Principe", 
                "woeid": "23424966"
            }
        }
    }
}

>>>

####insert(table, (field1, field2, ..., fieldN),(value1, value2, ..., valueN)) Insert values into a table. Arguments 2 and 3 may be tuples or list.

>>> from myql.utils import pretty_json
>>> response = yql.insert('yql.storage.admin',('value',),('http://josuebrunel.org',))
>>> print(pretty_json(response.content))
{
    "query": {
        "count": 1,
        "created": "2015-05-14T13:25:56Z",
        "lang": "en-US",
        "results": {
            "inserted": {
                "execute": "store://KkkC5xDw4v32IcWWSQ4YRe",
                "select": "store://Zc5LHXcmYM7XBfSbo9tzFL",
                "update": "store://Rqb5fbQyDvrfHJiClWnZ6q"
            }
        }
    }
}

####update(table,[field1, ..., fieldN],[value1, ..., ...valueN]).where(filters, ...) Update fields values. This method is always followed by where(). Arguments 2 and 3 may be tuples or list.

>>> from myql.utils import pretty_json
>>> response = yql.update('yql.storage',('value',),('https://josuebrunel.org',)).where(['name','=','store://Rqb5fbQyDvrfHJiClWnZ6q'])
>>> print(pretty_json(response.content))
{
    "query": {
        "count": 1,
        "created": "2015-05-14T13:32:52Z",
        "lang": "en-US",
        "results": {
            "success": "Updated store://KkkC5xDw4v32IcWWSQ4YRe"
        }
    }
}

####delete(table).where(filters, ...) Delete records

>>> from myql.utils import pretty_json
>>> response = self.yql.delete('yql.storage').where(['name','=','store://Rqb5fbQyDvrfHJiClWnZ6q'])
>>> print(pretty_json(response.content))
{
    "query": {
        "count": 1,
        "created": "2015-05-14T13:38:28Z",
        "lang": "en-US",
        "results": {
            "success": "store://Rqb5fbQyDvrfHJiClWnZ6q deleted"
        }
    }
}

####Using OAuth

mYQL comes with yahoo_oauth, which is an OAuth library for Yahoo! APIs.

>>> from yahoo_oauth import OAuth1
>>> oauth = OAuth1(None, None, from_file='credentials.json') # only consumer_key and consumer_secret are required.
>>> from myql import MYQL
>>> yql = MYQL(format='xml', oauth=oauth)
>>> response = yql.get_guid('josue_brunel') # Deal with the response

Stocks Scraper

The full documentation on StockScraper is here

Release Notes

1.2.6

1.2.5

  • camelCase dropped for underscore
  • Support for substitution variable i.e @myvar
  • Support of Remote Filters
  • Support of Post Query Filters
1.2.4

  • Weather module added
  • StockScraper now under Finance namespace
1.2.3

  • Fixed issue related to date in StockRetriver.get_historical_info #107
  • Fixed issue with IN condition in where clause #106
  • Fix definition of raw_input for python3 #105
  • Yahoo-OAuth included as main oauth library #112
1.2.2

  • Python3 support OK #71
  • PyPy/PyPy3 support OK
  • Fixed issue with IN condition in where clause
  • Fixed issue when passing an empty list/tuple ([]/()) in a where clause besides first argument
  • Import of StockParser from Gurchet Rai OK #68
  • Insert, Update, Delete methods added #67
  • Dummy try/except removed from main module
  • Fixed Invalid OAuth Signature when using a refreshed token #64
  • Fixed misused of MYQL.use(...) #76
  • Fixed format issue #82
  • Added useful functions in utils #81
  • Default access to community tables
  • Response prettyfier : pretty_json, pretty_xml
v 1.2.1

  • Multiple requests while using OAuth fixed
1.2.0

  • OpenTable classes
  • Access to resources requiring authentication
0.5.6

  • fetch data
  • access to community data
  • select data format (xml/json)
  • change data source
  • filter data
  • fix handling of default response format on the fly
  • fix limit on select(...).where(...) when no limit value is passed
  • fix limit on get(...)

myql's People

Contributors

aliounedia avatar gitter-badger avatar josuebrunel avatar kounkou avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

myql's Issues

Using meta classes for OpenTables

It would be fun, yeah just fun to be able define a YQL Table as follow :

class MySelect(yqltable.Section):
     name = 'select'
     url = yqltable.Section.Url('https://google.com')
     page = yqltable.Section.Page(model, start, pageSize, total)
     inputs = yqltable.Section.Input(id, type, paramType, required='false', like='')


class MyDataTable(yqltable.Table):
     name = 'foo'
     select = yqltable.Section(MySelect)

Unittests

You the routine now. Have fun buddy ^_^

Sorry budy this ain't pythonic at all

In _contrib/table/table.py_

def _init_table_elementTree(self, xml=True, db_table=True):
        """Create a table 
        """
        # <table> tag object
        t_table =  xtree.Element('table')
        # <table xmlns='' securityLevel='' htpps=''>
        if not self.table_attr :
            self.table_attr = self._TAB_ATTR
        for attr in self.table_attr.items() :
            t_table.set(*attr)

        # <meta>
        t_meta = xtree.SubElement(t_table, 'meta')

        ## <author>
        t_author = xtree.SubElement(t_meta, 'author')
        t_author.text = self.author
        ##

        ## <apiKeyURL>
        t_apiKeyURL = xtree.SubElement(t_meta, 'apiKeyURL')
        t_apiKeyURL.text = self.apiKey
        ##

        ## <documentationURL>
        t_documentationURL = xtree.SubElement(t_meta, 'documentationURL')
        t_documentationURL.text = self.documentationURL
        ##

        ## <description>
        t_description = xtree.SubElement(t_meta, 'description')
        t_description.text = self.description
        ##

        ## <sampleQuery>
        for sample_query in self.sampleQuery:
            t_sampleQuery = xtree.SubElement(t_meta, 'sampleQuery')
            t_sampleQuery.text = sample_query
        ##

        ## <bindings>
        t_bindings = xtree.SubElement(t_table, 'bindings')
        ##

        self.etree = t_table
        return t_table

SELECT method

To make it simple. The idea is to be able to something like this :

from lokingyql import LokingYQL as yql
lk = yql()
lk.select(<tablename>).where(<dict: conditions>)

Got it ?

USE method

This would be useful to work on some Open Data tables as described here.

What does it do:

Technically, it just changes the _self.url_ to the url provided

How to

>>> import lokingyql
>>> yql = lokingyql.LokingYQL()
>>> yql.use('http://myserver.com/mytables.xml')
>>>... # do your thing 

That's all !!!!

addInput method : AttributeError: etree

Traceback (most recent call last):
  File "table.py", line 30, in <module>
    class SelectBinder(BinderModel):
  File "table.py", line 16, in __init__
    dct[name] = Binder(**binder_attr)
  File "/home/yosuke/.virtualenvs/yql-cli/local/lib/python2.7/site-packages/lokingyql-0.5-py2.7.egg/lokingyql/contrib/table/binder.py", line 25, in __init__
    [ self.addInput(key.etree) for key in inputs ]
  File "/home/yosuke/.virtualenvs/yql-cli/local/lib/python2.7/site-packages/lokingyql-0.5-py2.7.egg/lokingyql/contrib/table/binder.py", line 86, in addInput
    t_input.append(key.etree)
AttributeError: etree

FIX

In file okingyql/contrib/table/binder.py

[ self.addInput(key) for key in inputs ]

instead of

[ self.addInput(key.etree) for key in inputs ]

Implements Unique function for YQL

select * from search.termextract where context in (
  select abstract from search.web(50) where query="elephant") 
| unique(field="Result")

Access to Community Tables

So far, there's no access to Community Tables. It would be great to have access to those tables.

To have access to those tables

env 'store://datatables.org/alltableswithkeys';

must be added before every single query requesting info on a community table.
In short the final request looks like this :

env 'store://datatables.org/alltableswithkeys'; desc yahoo.finance.quotes

List all available tables

A method called _showTables_ should be able to list all the available tables provided by the Yahoo ! API.

Limit Result

A _limit_ parameter is surely useful.

>>> yql.select('geo.countries', limit=5) # With select
>>> ...
>>> yql.get('geo.countries', ['name', 'woeid'], 5).where(['place', '=', 'Africa'])

Process request response according to format

**Blocking #2 **
The Yahoo! API provides 2 formats to get your results : xml or json. So according to the defined format, process the request response, to return information as clear as possible.
Have fun

WHERE method

The famous where clause.

What for

This method will receive one to several lists. Those lists contain filters which will be used in the where clause. It will raise an Error if there's no _self.table_, which means that there is no such thing as a selected table.

How to use

>>> yql.select('person', ['name', 'age']).where(['age', '>', '15'], ['location', '=', 'paris'])

That's all folks

rawQuerry method

The _rawQuery_ is very basic. It simply allows basic YQL query such as:

response = yql.query('select * from weather.forecast where woeid=2502265')
#Now deal with the response 

No need to specify the Yahoo ! API url though

OAUTH

Implements a method allowing LokingYQL to access data requiring authentification.

OpenTable

  • Create Table
  • Insert into Table
  • Update Table
  • Delete data in Table

GET Method

๐ŸŽฑ what does it do:

_GET_ is a fork of select, which instead returns a response. In short is a _select_ without that a _where_.
This should fix the issue #15

๐ŸŽฑ how to use:

>>> yql.get('geo.countries', ['name', 'woeid'], 5)

Allow raw_response to be returned

_Link to #6_

It would definitely be great to have a raw_response, by that we mean a none prettified one.

New Prototype:

def rawQuery(self, query, format='json', pretty=True):
    #Code

Load config from any file

It would be great if an user can load his/her oauth config from python anyfile

>>> import lokingyql
>>> yql = lokingyql.LokingYQL()
>>> yql.config_from('myconfig') # loads config from myconfig.py
>>> 

DESC method

What does it do:

Returns the description of a table

How to use:

>>> response =  yql.desc('geo.countries')

UTF-8 Encoding issue when creating xml file

<?xml version="1.0" encoding="utf-8"?>
<table https="false" securityLevel="any" xmlns="http://query.yahooapis.com/v1/schema/table.xsd">
        <meta>
                <author>Josue Kouka</author>
                <apiKeyURL>http://josuebrunel.org/api</apiKeyURL>
                <documentationURL>http://josuebrunel.org/doc.html</documentationURL>
                <description/>
                <sampleQuery>SELECT * FROM mytable</sampleQuery>
                <sampleQuery>SELECT name FROM mytable WHERE id=345</sampleQuery>
                <sampleQuery>SELECT * FROM mytable WHERE name=&quot;toto&quot;</sampleQuery>
        </meta>
        <bindings>
                <select itemPath="products.product" pollingFrequencySeconds="30" produces="xml">
                        <urls>
                                <url>http://lol.com/services?artist=$</url>
                                <url>http://lol.com/services/song=$</url>
                        </urls>
                        <inputs>
                                <key id="song" paramType="path" required="true" type="xs:string"/>
                                <key id="artist" paramType="path" required="false" type="xs:string"/>
                        </inputs>
                        <paging model="page">
                                <start default="1" id="ItemPage"/>
                                <total default="10"/>                                                                                 
                                <pageSize id="Count" max="25"/>                                                                       
                        </paging>                                                                                                     
                </select>                                                                                                             
        </bindings>                                                                                                                   
</table>                   

Errors Module

An Error Module must be written. And this issue will be updated throughout the project.

List of implemented Errors:

  • _NoTableSelectedError_

Ugly binding of a Binder with a Table in TableModel definition

Buddy, i only find one word for this ugly last line, and this word buddy is _UGLY_.

class TestTable(TableModel):
    name = 'Test'
    author = 'Josue Kouka'
    apiKeyURL = 'http://josuebrunel.org/api'
    documentationURL = 'http://josuebrunel.org/doc.html'
    sampleQuery = 'SELECT * FROM mytable'
    select = SelectBinder

Can't you make something a lil more pythonic ( Python is beautiful, don't make it UGLY )

class TestTable(TableModel):
    name = 'Test'
    author = 'Josue Kouka'
    apiKeyURL = 'http://josuebrunel.org/api'
    documentationURL = 'http://josuebrunel.org/doc.html'
    sampleQuery = 'SELECT * FROM mytable'
    select = BindTo(SelectBinder)

I don't know, find something

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.