Git Product home page Git Product logo

python-oauth2's Introduction

Join the chat at https://gitter.im/joestump/python-oauth2 Build Status Coverage Number of issues Licence MIT

Note: This library implements OAuth 1.0 and not OAuth 2.0.

Overview

python-oauth2 is a python oauth library fully compatible with python versions: 2.6, 2.7, 3.3 and 3.4. This library is depended on by many other downstream packages such as Flask-Oauth.

Installing

You can install oauth2 via the PIP package.

$ pip install oauth2

We recommend using virtualenv.

Examples

Examples can be found in the wiki

Running tests

You can run tests using the following at the command line:

$ pip install -r requirements.txt
$ python setup.py test

History

This code was originally forked from Leah Culver and Andy Smith's oauth.py code. Some of the tests come from a fork by Vic Fryzel, while a revamped Request class and more tests were merged in from Mark Paschal's fork. A number of notable differences exist between this code and its forefathers:

  • 100% unit test coverage.
  • The DataStore object has been completely ripped out. While creating unit tests for the library I found several substantial bugs with the implementation and confirmed with Andy Smith that it was never fully baked.
  • Classes are no longer prefixed with OAuth.
  • The Request class now extends from dict.
  • The library is likely no longer compatible with Python 2.3.
  • The Client class works and extends from httplib2. It's a thin wrapper that handles automatically signing any normal HTTP request you might wish to make.

python-oauth2's People

Contributors

admp avatar alexwlchan avatar brosner avatar chilic avatar chrisdickinson avatar dougireton avatar edsu avatar groodt avatar hbs avatar ieure avatar jaitaiwan avatar joestump avatar jparise avatar jplock avatar martyni avatar mmalone avatar muffinresearch avatar nikolas avatar prehensile avatar rickhanlonii avatar rodericj avatar sbraz avatar sebpiq avatar stevepeak avatar sylvainde avatar timsc avatar tseaver avatar tswicegood avatar woodya avatar zookos 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  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  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  avatar  avatar  avatar  avatar

Watchers

 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  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  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  avatar  avatar  avatar  avatar

python-oauth2's Issues

get_normalized_parameters does not take into account the 2 legged OAuth with oauth params in the URL

hello,

While tweaking around to get two legs OAuth working I realised that get_normalized_parameters in Request does not take into accoutn the case where the URL has oauth authentification GET variables like the following:

api/v2.1/users?oauth_nonce=34400401&oauth_timestamp=1276109986&oauth_consumer_key=N_S3ZhJypOv1CW3IWa&oauth_signature_method=HMAC-SHA1&oauth_version=1.0&oauth_signature=AuJ6QulDbLkWz9Ss%2FbbBMKerLKw%3D HTTP/1.1"

Which is valid.

We just need to add something like

    get_items = self._split_url_string(query).items()
    non_getl_items = list([(k, v) for k, v in url_items  if not k.startswith('oauth_')])

Or i missed something obvious.

tests package installed stupidly

1.5.170 installs the tests in site-packages/tests. This is obviously not a good idea: at the very least, prone to collisions with some other packages. It seems to happen because setuptools.find_packages() correctly finds the tests package and then installs it.

I think there are two viable options of resolving this:

  • don't install the tests
  • move the tests into the oauth2 package

I'd be happy to contribute a patch, but I don't think that would be the sticky point here.

test_oauth.py fails to import oauth2 unless oauth2 is already installed

Running the tests without installing oauth2 fails, this appears to be a simple case of not updating the library path before doing the import. The error is below.

python-oauth2/tests$ python test_oauth.py
Traceback (most recent call last):
File "test_oauth.py", line 29, in
import oauth2 as oauth
ImportError: No module named oauth2

Multi-value variables incorrectly handled

the library incorrectly handles multiple occurrences of a parameter.

For example: http://foo.bar.net/path?a=123&a=456

Request being a such a thin wrapper over dict is problematic here. At the very least is needs to be a dictionary of lists (a list of tuples is a bit harder to work with). Which would require a custom urlencode and a custom update() method.

content-types that start with 'application/x-www-form-urlencoded' should not be treated as multi-part

The request() method in the Client class in oauth2/__init__py has this statement:

is_multipart = method == 'POST' and headers.get('Content-Type', DEFAULT_CONTENT_TYPE) != DEFAULT_CONTENT_TYPE

This means that content-types like "application/x-www-form-urlencoded; charset=utf-8" will make is_multipart evaluate to True. Can it be changed to something like this please?

is_multipart = method == 'POST' and not headers.get('Content-Type', DEFAULT_CONTENT_TYPE).startswith(DEFAULT_CONTENT_TYPE)

Thanks

get_normalized_parameters() appends non oauth parameters twice

get_normalized_parameters is appending duplicate non-oauth parameters to the returned value of this method causing the method signature check to fail.

So a call to this url http://example.com/v2/search/videos?oauth_nonce=79815175&oauth_timestamp=1295397962&oauth_consumer_key=mykey&oauth_signature_method=HMAC-SHA1&q=car&oauth_version=1.0&offset=10&oauth_signature=spWLI%2FGQjid7sQVd5%2FarahRxzJg%3D

will cause get_normalized_parameters() to return oauth_consumer_key=mykey&oauth_nonce=79815175&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1295397962&oauth_version=1.0&offset=10&offset=10&q=car&q=car

notice the duplicate "offset" and "q" parameters.

Possible error in flow when callback are used

While looking at the various clients/examples I got the feeling that the flow used when a callback is needed is kind of incorrect.

Basically, in the sample code the callback is submitted to the service provider once the request token must be authorized by the end user.

According to Twitter Oauth the callback should be submitted to the service provide when obtaining the request token. This makes some sense as the server provider may decide not to confirm the callback and so the consumer will have to change the strategy used when authorizing the request token from callback to user input validation.

While I've been able to go around this issue, by including special headers and so, I think it would be worth reviewing this scenario and making sure it is correct

Does not build on OpenBSD (corrections included)

Appears to require gmake rather than make, which I resolved by invoking via correct name (didn't see any hints to do this).

The following:
DEPS := $(shell find $(PWD)/deps -type f -printf "file://%p ")
does not work with BSD find (no -printf), changed to:
DEPS := $(shell find $(PWD)/deps -type f -exec echo "file://{} " ;)

Similarly:
SOURCES := $(shell find $(SRCDIR) -type f -name .py -not -name 'test__')
does not work with BSD find (no -not), changed to:
SOURCES := $(shell find $(SRCDIR) -type f ( -name _.py -and ! -name 'test_
' ))

After making the above changes I was able to 'gmake' successfully on OpenBSD 4.8/macppc.

Delicious signature error

Hi,

I'm seeing what might be either a regression or a problem with my usage of the oauth2 library. I have a Delicious set up script here: https://gist.github.com/1f0b8ebb4f772da7df57

It works with version 1.2.0, but breaks with the latest (to be 1.2.1) git version. I've created 2 pip virtualenvs to verify this. The error output is this:

{'status': '401', 'transfer-encoding': 'chunked', 'connection': 'close', 'date': 'Mon, 30 Aug 2010 17:03:59 GMT', 'p3p': 'policyref="http://info.yahoo.com/w3c/p3p.xml", CP="CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE LOC GOV"', 'content-type': 'application/x-www-form-urlencoded', 'www-authenticate': 'OAuth oauth_problem=signature_invalid'}
Traceback (most recent call last):
  File "delicious_oauth.py", line 21, in <module>
   raise Exception("Invalid response %s." % resp['status'])
Exception: Invalid response 401.

Inclusion of oauth_body_hash breaks Hyves API

I'm using python-oauth2 to make calls to the Hyves API (http://www.hyves-developers.nl/). This was working perfectly fine before, until python-oauth2 started including oauth_body_hash in the requests. Now Hyves borks, telling me that oauth_body_hash is an unknown parameter.

In a previous version of the oauth specification it clearly says (http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/drafts/4/spec.html#rfc.section.3):

The body hash parameter MUST NOT be sent on HTTP GET or HEAD requests.
The body hash parameter SHOULD be sent on all other requests.

make_nonce is not random enough

When doing bulk operations it is quite easy for requests to go out with the same timestamp. If I leave a bulk operation going at up to 60 requests a minute (often they all go out in the first 10s) then it will almost certainly use a duplicate timestamp/nonce pair within about 20 minutes.

I'd say that make_nonce needs to also take into account the current time in microseconds and maybe even the pid.

Using sleep() is my current method but I don't think it should be needed.

oauth2.Request strips query parameters from the URL

The fancy setter (Request.url) strips query parameters from the original URL. In cases where you are using Authorization headers there is no clean way to get the query parameters back.

I might come up with a patch, time permitting.

Please provide an example for Requesting User Authorization

Can you please provide an example of Requesting User Authorization? See OAuth spec section "6.2.1. Consumer Directs the User to the Service Provider".

I am trying to access Twitter from Django using OAuth. Thanks for all your work so far.

Support for oauth echo

When writing a plugin that accesses a 3rd party twitter service, I needed the echo oauth method that is not currently implemented. This can be easily implemented by creating two requests and then adding the twitter.com authorization header to the 3rd party url.

python-oauth2 152: Twitter API always return Error 401 with utf-8 parameter

Hi

After upgrade python-oauth2 to 152 and trying to update twitter status using string encode to utf-8 twitter always return error:

{'status': '401'}
{"request":"/1/statuses/update.json","error":"Incorrect signature"}')

here's string that I tried to POST to twitter: status=ué¿q s,apa u.s?..a
and here's the result from httplib2 debug: status=Bu%3F%3Fq%20s%2Capa%20u.s%3F..a

urllib.unquote('status=Bu%3F%3Fq%20s%2Capa%20u.s%3F..a')
'status=Bu??q s,apa u.s?..a'

after removing this 2 lines everything working normal.

329 k = to_unicode(k)
330 v = to_unicode_optional_iterator(v)

After Request PIn...

After request pin, and insert into Test.py i've this error

File "tests/test-tw.py", line 59, in
print " - oauth_token = %s" % access_token['oauth_token']
KeyError: 'oauth_token'

Twitter Three-legged OAuth Example has a flaw

As currently shown the example will always fail after the pincode is given with a 401 error. The reason is that oAuth v1.0a requires that the oauth_verifier parameter be present in the POST that is making the access token request.

The fix is to add the it as part of the body parameter:

resp, content = client.request(access_token_url, "POST", body="oauth_verifier=%s" % oauth_verifier)

Split client out of main __init__.py file

The current structure of the library mixes OAuth signing tools with http client library code - specifically synchronous http library code. We use Twisted, and would like to use all the great signing code without having to have httplib2 installed.

I'm thinking it might be nicer to have it moved to the clients sub-package and possibly have some import logic in init.py with a try/except ImportError around httplib2.

Client.request mangles query strings

If I try to make an OAuth signed request to the following URL:

http://api.twitter.com/1/users/show.json?screen_name=simonw

I get this error:

{u'request': u'/1/users/show.json?oauth_version=1.0&oauth_token=...&screen_name=%5B%27simonw%27%5D&oauth_nonce=...&oauth_timestamp=...&oauth_signature=...&oauth_consumer_key=...&oauth_signature_method=HMAC-SHA1', u'error': u'Not found'}

The screen_name value has been passed through as:

%5B%27simonw%27%5D

Which URL decodes to the following string:

"['simonw']"

What's happened here is that somewhere inside the oauth2 library my original ?screen_name=simonw querystring has been decoded in to a list, using cgi.parse_qs - and that list has then been converted in to a string using Python's default string representation.

I think the code at fault is on line 578 in the Client.request method:

elif method == "GET":
    parsed = urlparse.urlparse(uri)
    parameters = parse_qs(parsed.query)

That third line should be:

    parameters = dict(parse_qsl(parsed.query))

Adding a body to a client request will not work in python versions before 2.6

The urlparse .parse_qs and .parse_qsl methods were added in the library in python 2.6. In previous versions they are located in the cgi module.

If python2.5 compatibility is required the imports need to be handled accordingly.

Is this intentional? If not a simple patch can be provided to clear up the issue.

setup.py should specify package dependencies

oauth2 requires httplib2, but this isn't specified in setup.py. If you add:

install_requires = [ 'httlib2', ]

to your setup() call, easy_install will be able to automatically install httlib2 during the oauth2 install.

Consider adding lib version info

Right now there is no way to know which version of oauth2 is loaded on a server. The VERSION string of "1.0" is also a bit confusing. For example, I have oauth2 installed via pip into a virtualenv. The setup.py file is the only place I can find here on github that references version 1.2.0 but that's not on the server, and hence, on the server, there is no indication that I have 1.2.0 or something else.

_check_timestamp() doesn't raise error when timestamp is greater than current time

Looks like this method doesn't really care if the timestamp is pointing to distant future.

def _check_timestamp(self, timestamp):
    """Verify that timestamp is recentish."""
    timestamp = int(timestamp)
    now = int(time.time())
    lapsed = now - timestamp
    if lapsed > self.timestamp_threshold:
        raise Error('Expired timestamp: given %d and now %s has a '
            'greater difference than threshold %d' % (timestamp, now,
                self.timestamp_threshold))

If the timestamp is greater than current time, 'lapsed' variable will be negative, and therefore always false.

500 > 300
True
-500 > 300
False

I fixed it like this to my code:

if abs(lapsed) > self.timestamp_threshold:

Python 2.4 (small) issue (module is callable error)

There is an error when this module runs in python 2.4. I put a small patch inline here because github won't let me attach files:

diff -r 89426279318c -r ea8401431426 oauth2/__init__.py
--- a/oauth2/__init__.py    Mon Feb 14 21:35:07 2011 +0200
+++ b/oauth2/__init__.py    Mon Feb 14 21:36:07 2011 +0200
@@ -471,7 +471,7 @@
             # section 4.1.1 "OAuth Consumers MUST NOT include an
             # oauth_body_hash parameter on requests with form-encoded
             # request bodies."
-            self['oauth_body_hash'] = base64.b64encode(sha(self.body).digest())
+            self['oauth_body_hash'] = base64.b64encode(sha.new(self.body).digest())
 
         if 'oauth_consumer_key' not in self:
             self['oauth_consumer_key'] = consumer.key

RSA signature method

Thanks for writing this very useful library.
I could not see a SignatureMethod_RSA method included in the source, so I wrote one that uses M2Crypto. I am not sure if it will be useful for someone else, but here is the code in case it might be.

"""
A signature method class for RSA signing, for use with oauth2.
Requires M2Crypto
"""
import base64
import hashlib
import oauth2
from M2Crypto import RSA

class SignatureMethod_RSA(oauth2.SignatureMethod):
""" RSA signature not implemented by oauth2."""
name = "RSA-SHA1"

def __init__(self, key_path):
    super(oauth2.SignatureMethod, self).__init__()
    self.key_path = key_path
    self.RSA = RSA.load_key(key_path)

def signing_base(self, request):
    """Calculates the string that needs to be signed."""
    sig = (
        oauth2.escape(request.method),
        oauth2.escape(request.normalized_url),
        oauth2.escape(request.get_normalized_parameters()),
    )
    raw = '&'.join(sig)
    return raw

def sign(self, request, consumer, token):
    """Returns the signature for the given request.
    Note: consumer and token are not used, but are there to fit in with
    call in oauth2 module.
    """
    raw = self.signing_base(request)
    digest = hashlib.sha1(raw).digest()
    signature = self.RSA.sign(digest, algo="sha1")
    encoded = base64.b64encode(signature)
    return encoded

Oauth Echo Client

For one of my project I had to build I had to build a Oauth Echo "client" to be able to post object to twitter related service : twitpic, yfrog ...

This is way more difficult than it should and I am wondering if you would be ready to consider the inclusion of an "EchoClient" that would abstract this. This client would take care of building the appropriate headers.

Regards,
--yml

Python 2.4 compatibility problem with urlparse

I have setup a simple Client with v1.1.3 as in your Twitter example but I get the following error

File "/var/lib/zope3/instance/satisfly/lib/python/satisfly/browser/connections.py", line 272, in call
print client.request(request_token_url, "GET")
File "build/bdist.linux-x86_64/egg/oauth2/init.py", line 622, in request

File "build/bdist.linux-x86_64/egg/oauth2/init.py", line 317, in to_url

I investigated a bit and I noticed that you are expecting urlparse.urlparse returning an object with a query property:

def to_url(self):
    """Serialize as a URL for a GET request."""
    base_url = urlparse.urlparse(self.url)
    query = parse_qs(base_url.query)
    [...]

But my version returns a 6-tuple

Tnx for your help

Regards

uppercase 'Authorization' header

Integrated python-oauth2 with twisted framework. Twisted sets all headers names to lowercase while the oauth module expects uppercase 'Authorization'. Rather that a hack to revert the header before calling oauth routimes (from_request for example) any suggestions how to better handle this?

404 not found on setup.py install

Seems to be bad mirror in setup.py script?

Installed /usr/local/lib/python2.6/dist-packages/oauth2-1.2.1-py2.6.egg
Processing dependencies for oauth2==1.2.1
Searching for httplib2==0.4.0
Reading http://pypi.python.org/simple/httplib2/
Reading http://code.google.com/p/httplib2/
Reading http://bitworking.org/projects/httplib2/
Best match: httplib2 0.4.0
Downloading http://bitworking.org/projects/httplib2/dist/httplib2-0.4.0.tar.gz
error: Can't download http://bitworking.org/projects/httplib2/dist/httplib2-0.4.0.tar.gz: 404 Not Found
user@userlaptop:~/Documents/python-oauth2$

Properly mock all tests requiring network access.

Most tests do not require networking, but test_access_token_get, test_access_token_post, test_two_legged_get and test_two_legged_post do. Please provide an easy way to run only tests which do not require networking.

What example code to use?

The example code in the readme.md file and the example code downloaded with the source code are very different, which should I be using?

unicode problems

The library has issues dealing with normalizing url query key/value pairs that are unicode because of urllib.urlencode. I've posted a small patch for oauth2/init.py at http://pastebin.com/6U5PWC3z , wanted to confirm that this is a problem.

Parameters containing tilde characters are incorrectly escaped

oauth2.Request.get_normalized_parameters uses urllib.urlencode, which percent-encodes the tilde character (~). This conflicts with RFC 5849, section 3.6, which states that ~ must not be percent-encoded. This means that oauth2 currently generates incorrect signatures for requests whose parameters contain a tilde.

oauth_callback should be sent when requesting a request token

It's currently difficult to send the oauth_callback parameter when requesting a request token (as per section 6.1.1 of the oauth 1.0a community spec: http://oauth.net/core/1.0a/#auth_step1). In order to make it work, I had to include the oauth_callback param in the 'body' of the client request:

import urllib
import oauth2 as oauth

key = 'mykey'
secret = 'mysecret'
callback_uri = 'http://mycallback/uri'

consumer = oauth.Consumer(key, secret)
client = oauth.Client(consumer)
client.set_signature(oauth.SignatureMethod_PLAINTEXT())

get the request token

body = urllib.urlencode(dict(oauth_callback=callback_uri))
resp, content = client.request(request_token_uri, 'POST', body=body)

This feels like a hack and isn't clear from reading any of the examples. It would be much more intuitive if the caller was able to pass the callback uri as a kwarg to the client constructor or to the request method, i.e.:

client = oauth.Client(..)
...
client.request(uri, 'POST', callback=callback)

Can't send unicode/utf-8 body with Python 2.7

The httplib in Python 2.7 has changed and tries to merge the headers and body if the body is an instance of str/unicode (lines 794-796 in 2.7's httplib.py).

For some reason init for oauth2's Request class (lines 348-341 in init.py) converts the parameter keys to unicode and so the entire request header will always be a unicode object (unicode + str = unicode). I'm not really sure why oauth2 does this since all parameter values are converted to strings anyway (line 392).

The end result is that I can't send any unicode/utf-8 data with oauth2 and Python 2.7 because:

  • Sending a utf-8 encoded string raises a UnicodeDecodeError when httplib tries to append it to the unicode header.
  • Sending a unicode object raises a UnicodeDecodeError on line 493 when oauth2 tries to hash the body.
  • Sending a file like object raises a TypeError on line 493 when oauth2 tries to hash the body.

parameters in http_url incorrectly handled in Request.from_request()

When the http_url parameter is parsed to see if it contains any params, the paramsaren't removed from the url after being added to the parameters variable. Request.get_normalized_parameters() also parses the raw url (why?) when constructing the cignaturebasestring. The combination of these actions is that parameters coming from http_url get included twice in the signature base string.

Fix:

  • in from_request, after parsing http_url: http_url = http_url.split('?',1)[0]

It's not clear that you need or want to parse the original url again in get_normalized_parameters, it would be cleaner is all constructors and factories ensured that parameters get extracted on creation so you can just use the reqeust dictionary and the normalized url.

Path in base string uri does not support matrix parameters

Im trying to use python-oauth2 against Yahoo! OAuth APIs. Yahoo! makes extensive use of matrix parameters in their APIs. Example here: http://developer.yahoo.com/social/rest_api_guide/social_dir_api.html#social_dir_intro-matrix_params Unfortunately, python-oauth2 does not seem to calculate the oauth signature correctly when there are matrix params. Matrix params are supported in the spec: in the OAuth RFC http://tools.ietf.org/html/rfc5849#section-3.4.1.2 it mentions the path should be valid according to http://tools.ietf.org/html/rfc3986#section-3.3 This section of the spec does seem to accept matrix params, and Yahoo! would hopefully not be providing non-valid OAuth APIs.

I've tracked it down to the use of urlparse.urlparse(). This is dropping the matrix params. I think we should be using urlparse.urlsplit() instead.

test_access_token_post test fails on invalid assertion on line 722

FAIL: Test getting an access token via POST.

Traceback (most recent call last):
File "test_oauth.py", line 722, in test_access_token_post
self.assertTrue('oauth_token_key' in res)
AssertionError

EXPECT:
All tests shoud pass. Fix line 722 as follows
self.assertTrue('oauth_token' in res)

PUT Implementation Broken

When signing the OAuth request, it seems that PUT requests are not properly signed. I am able to properly authenticate to any number of APIs via GET and POST, but PUT fails to authenticate properly.

This is a function of the API that I am accessing, but reproducing with the Assistly API is something like this:

PUT requests are seen as GET requests (specifically when updating an object). When the form-urlencoded header is manually added, the API sees the request as PUT, but throws a 401 Unauthorized error, indicating that the signing is incorrect, because a GET request right before that PUT with the same OAuth credentials succeeds.

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.