Giter Site home page Giter Site logo

bashu / django-secretballot Goto Github PK

View Code? Open in Web Editor NEW
208.0 208.0 69.0 157 KB

🗳 Django voting application that allows semi-anonymous voting

Home Page: https://django-secretballot.readthedocs.io

License: BSD 2-Clause "Simplified" License

Python 99.73% HTML 0.27%
django

django-secretballot's Introduction

There's nothing to see here. Move along. Keep moving.

django-secretballot's People

Contributors

afnarel avatar bashu avatar drinks avatar hedleyroos avatar jamesturk avatar kant avatar kneirinck avatar kreativitea avatar msgre avatar nick13jaremek avatar phala avatar smn avatar tpilewicz 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

django-secretballot's Issues

broken tests with AppConfig.ready

Django==2.1.2
djangorestframework==3.8.2
django-secretballot==1.0.0
pytest-django==3.4.3
Python 3.7.0

When I use the following apps.py code

from django.apps import AppConfig
import secretballot


class MyConfig(AppConfig):
    name = 'app'
    verbose_name = 'My project'

    def ready(self):
        host_model = self.get_model("Host")
        # secretballot.enable_voting_on(host_model)

My full test suite (111 tests) passes

If I uncomment the enable_voting_on line, pytest breaks during collection collected 83 items / 4 errors with errors like this:

================================================== ERRORS ==================================================$
_________________________________ ERROR collecting app/tests/admin_tests.py ________________________________$
/usr/local/lib/python3.7/site-packages/py/_path/local.py:668: in pyimport                                    
    __import__(modname)                                                                                     
app/tests/__init__.py:6: in <module>
    from .viewsets_tests import *  # noqa: F401, F403                                                       
app/tests/viewsets_tests/__init__.py:7: in <module>
    from .user_tests import *                                                                               
<frozen importlib._bootstrap>:983: in _find_and_load                                                        
    ???                                                                                                     
<frozen importlib._bootstrap>:967: in _find_and_load_unlocked                                               
    ???                                                                                                     
<frozen importlib._bootstrap>:668: in _load_unlocked                                                        
    ???                                                                                                     
<frozen importlib._bootstrap>:638: in _load_backward_compatible                                             
    ???                                                                                                     
/usr/local/lib/python3.7/site-packages/_pytest/assertion/rewrite.py:290: in load_module                     
    six.exec_(co, mod.__dict__)                                                                             
app/tests/viewsets_tests/user_tests.py:12: in <module>                                                      
    from app.viewsets import UserViewSet                                           
app/viewsets/__init__.py:6: in <module>
    from .hosts import HostViewSet  # noqa F401
app/viewsets/hosts.py:8: in <module>
    class HostViewSet(viewsets.ModelViewSet):
app/viewsets/hosts.py:9: in HostViewSet
    queryset = Host.objects.filter(display=True)
/usr/local/lib/python3.7/site-packages/django/db/models/manager.py:82: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
/usr/local/lib/python3.7/site-packages/secretballot/__init__.py:59: in get_queryset
    content_type = ContentType.objects.get_for_model(self.model).id
/usr/local/lib/python3.7/site-packages/django/contrib/contenttypes/models.py:51: in get_for_model
    ct = self.get(app_label=opts.app_label, model=opts.model_name)
/usr/local/lib/python3.7/site-packages/django/db/models/manager.py:82: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
/usr/local/lib/python3.7/site-packages/django/db/models/query.py:393: in get
    num = len(clone)
/usr/local/lib/python3.7/site-packages/django/db/models/query.py:250: in __len__
    self._fetch_all()
/usr/local/lib/python3.7/site-packages/django/db/models/query.py:1186: in _fetch_all
    self._result_cache = list(self._iterable_class(self))
/usr/local/lib/python3.7/site-packages/django/db/models/query.py:54: in __iter__
    results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
/usr/local/lib/python3.7/site-packages/django/db/models/sql/compiler.py:1063: in execute_sql
    cursor = self.connection.cursor()
/usr/local/lib/python3.7/site-packages/django/db/backends/base/base.py:255: in cursor
    return self._cursor()
/usr/local/lib/python3.7/site-packages/django/db/backends/base/base.py:232: in _cursor
    self.ensure_connection()
E   Failed: Database access not allowed, use the "django_db" mark, or the "db" or "transactional_db" fixture$
 to enable it.

All errors seem to occur in my host viewset, which looks like this

class HostViewSet(viewsets.ModelViewSet):
    queryset = Host.objects.filter(display=True)
    serializer_class = HostSerializer
    lookup_field = 'slug'

Commenting the queryset line of this viewset fixes the collection and 109 tests pass (only those related to the viewset break due to missing queryset).

It's interesting to see that the viewset related to the model with voting enabled would fail this way.
@jamesturk do you have a suggestion to fix the queryset line ? Or should this be supported by django-secretballot and require some modification on secretballot's side ?

Determining if voting is enabled for a class

I need a way to query a class to see if voting is enabled for it. I cannot safely do eg. hasattr(cls, 'votes') because the enable_voting_on function allows the caller to specify names for the attributes.

My proposal is to add this line to the bottom of function enable_voting_on:

setattr(class, '_voting_enabled', 1)

This unique attribute (aka marker) will allow me to check if voting is enabled without having to worry about custom attribute names specified to enable_voting_on.

migration error

Getting issue when migrating everything in empty database. After command manage.py migrate getting error:

File "/home/mazvydas/Envs/fakelife_test/local/lib/python2.7/site-packages/django/db/models/manager.py", line 228, in all
return self.get_queryset()
File "/home/mazvydas/Envs/fakelife_test/local/lib/python2.7/site-packages/secretballot/init.py", line 58, in get_queryset
content_type = ContentType.objects.get_for_model(self.model).id
File "/home/mazvydas/Envs/fakelife_test/local/lib/python2.7/site-packages/django/contrib/contenttypes/models.py", line 80, in get_for_model
"Error creating new content types. Please make sure contenttypes "
RuntimeError: Error creating new content types. Please make sure contenttypes is migrated before trying to migrate apps individually.

I'm sure this is caused by __init__.py file trying to query ContentType which has been not migrated to database at the time.

Workaround was editing init.py file where it queries database

try:
    content_type = ContentType.objects.get_for_model(self.model).id
except:
    content_type = None

while migrating.

Invalid default JSON response

The default JSON response uses single quotes in the variable name, but JSON requires double strings. Simple fix on line 71 of views.py:

body = "{'num_votes':%d}" % votes

to

body = '{"num_votes":%d}' % votes

Error when no HTTP_USER_AGENT is sent to API

This issue is encountered when you try to post without sending User Agent. Doing so causes following error:
KeyError: ‘HTTP_USER_AGENT’

Issue:
request.META[''HTTP_USER_AGENT''] is unable to find user agent in 'middleware.py'.

Likes for Users

models.py

import secretballot
from django.contrib.auth.models import User
secretballot.enable_voting_on(User)

All works fine.
By if I trying migrate db, i've got.
ValueError: Could not find manager VotableManager in secretballot.
Please note that you need to inherit from managers you dynamically generated with 'from_queryset()'.

This project needs a maintainer.

Hi,

This repository seems to lack maintenance, I propose myself as a new maintainer.

Could you give me the right to push in your repository or just transfer it on my account in github?

Thank you

Django 1.7 compatibility

/home/zanklord/programas/python/hearthstone/webapp/secretballot/init.py:48: RemovedInDjango18Warning: VotableManager.get_query_set method should be renamed get_queryset.
class VotableManager(base_manager):

solved renaming "def get_query_set(self):" to "def get_queryset(self):"

Unicode-objects must be encoded before hashing

Used the latest version of django-secretballot, django v.1.9.5, used python3 and it raises an error after launching server

Internal Server Error: /
Traceback (most recent call last):
  File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/core/handlers/base.py", line 123, in get_response
    response = middleware_method(request)
  File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/secretballot/middleware.py", line 6, in process_request
    request.secretballot_token = self.generate_token(request)
  File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/likes/middleware.py", line 19, in generate_token
    return md5(s).hexdigest()
TypeError: Unicode-objects must be encoded before hashing

middleware causes failure of tests

I am pretty green with python and django so I am not confident that your code is the problem. But when I comment out the middleware (SecretBallotIpUseragentMiddleware) the tests all pass.

Doesn't cooperate with get_object_or_404

Objects with voting enabled that are retrieved using django.shortcuts.get_object_or_404 don't have the total_upvotes and total_downvotes attributes for some reason. This causes the total_votes property to fail as well. Not sure what to suggest as far as a fix goes, but it's worth investigating.

setup.py does not install migrations

Setup.py do not install content in the secretballot.migrations package. This code fixes this:

setup(
    ...
    package_dir={'secretballot': 'secretballot'},
    packages=['secretballot', 'secretballot.migrations'],
    package_data={
        'secretballot': [
            'migrations/*.*',
        ],
    },
    zip_safe=False,
    ...
)

zip_safe is necessary because migrations do not work properly on eggs.

add tests for current behavior

  • middleware
  • enable_voting_on, add_vote, remove_vote, get_total, from_token, from_request, secretballot_enabled
  • Vote Model
  • vote view

Hey

How can I contribute?

middleware error

I got this error
[Sun Sep 08 18:53:01 2013] [error] [client 127.0.0.1] raise exceptions.ImproperlyConfigured('%s isn't a middleware module' % middleware_path)
[Sun Sep 08 18:53:01 2013] [error] [client 127.0.0.1] ImproperlyConfigured: SecretBallotIpUseragentMiddleware isn't a middleware module

Do I define it right?
MIDDLEWARE_CLASSES = (
'SecretBallotIpUseragentMiddleware',
)

How to get top rated objects?

My model:

 class Question(models.Model):
      title   = models.CharField(max_length=100)
      body = models.CharField(max_length=200)

  secretballot.enable_voting_on(Question)

So, I'm trying to get op rated objects:

  Question.objects.all().order_by('vote_total') 

and get this error:

 FieldError: Cannot resolve keyword 'vote_total' into field. Choices are: body, id, titel, votes

What i'm doing wrong?

What is the best way to integrate secretballot with DRF ?

I have a Django Rest Framework api, and integrated secretballot with one of my models.

I see that django-secretballot auto-generated some views

$ docker exec -ti $(docker ps |grep 'backend'|awk '{print $1}') ./manage.py show_urls | grep vote
/secretballot/vote/     django.contrib.admin.options.changelist_view  admin:secretballot_vote_changelist
/secretballot/vote/<path:object_id>/    django.views.generic.base.RedirectView
/secretballot/vote/<path:object_id>/change/     django.contrib.admin.options.change_view       admin:secretballot_vote_change                                                                                                   
/secretballot/vote/<path:object_id>/delete/     django.contrib.admin.options.delete_view       admin:secretballot_vote_delete                                                                                                   
/secretballot/vote/<path:object_id>/history/    django.contrib.admin.options.history_view      admin:secretballot_vote_history                                                                                                  
/secretballot/vote/add/ django.contrib.admin.options.add_view   admin:secretballot_vote_add
/secretballot/vote/autocomplete/        django.contrib.admin.options.autocomplete_view admin:secretballot_vote_autocomplete

But we only make public our api (all urls starting with /api/), and I'd like a format that is more aligned to DRF standards.
@jamesturk have you already used DRF before ? if yes, do you have any suggestion for a solution more tightly coupled with DRF ? Other projects have a viewset or serializer available to make it DRF-compatible.

SecretBallotIpUseragentMiddleware raises if RequestContext is not used

Some 3-rd party applications may not use RequestContext instances to show their pages. This is very annoying, but sometimes I can't do anything with it.
I suggest you to use
request.META.get('REMOTE_ADDR', 'Not defined')

instead
request.META['REMOTE_ADDR']

This will help to override 500 errors sometimes.

Accessor problems

I am receiving the following error on one of my models.
One or more models did not validate:
modelname: Accessor for m2m field 'votes' clashes with related m2m field 'Vote.modelname_set'

Assistance highly appreciated

`content_type.get_object_for_this_type` does not use the replacement manager

Refer to https://github.com/jamesturk/django-secretballot/blob/master/secretballot/views.py#L54. If the template being rendered uses get_total from https://github.com/jamesturk/django-secretballot/blob/master/secretballot/__init__.py#L42 then the VotableManager is not used, resulting in attributes upvotes_name and downvotes_name not being glued to the object.

I'll try and recreate the problem in a test.

I don't see any immediate solution yet except for a nasty hack in the get_total method.

Please release 0.5.1 to PyPi

Hi. django-likes has dependency on secretballot but it needs a new release for 1.9+ compatibility. The secretballot repo's latest code is ready for 1.9+.

AttributeError: object has no attribute 'total_upvotes'

Without Ajax it worked well, but with ajax:

Internal Server Error: /likes/like/interview_questions-problem/23/1
Traceback (most recent call last):
File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/template/base.py", line 883, in _resolve_lookup
current = current[bit]
TypeError: 'Problem' object is not subscriptable

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/core/handlers/base.py", line 149, in get_response
    response = self.process_exception_by_middleware(e, request)
  File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/core/handlers/base.py", line 147, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/likes/views.py", line 49, in like
    "content_type": url_friendly_content_type,
  File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/secretballot/views.py", line 66, in vote
    body = t.render(c)
  File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/template/backends/django.py", line 95, in render
    return self.template.render(context)
  File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/template/base.py", line 206, in render
    return self._render(context)
  File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/template/base.py", line 197, in _render
    return self.nodelist.render(context)
  File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/template/base.py", line 992, in render
    bit = node.render_annotated(context)
  File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/template/base.py", line 959, in render_annotated
    return self.render(context)
  File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/template/defaulttags.py", line 326, in render
    return nodelist.render(context)
  File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/template/base.py", line 992, in render
    bit = node.render_annotated(context)
  File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/template/base.py", line 959, in render_annotated
    return self.render(context)
  File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/template/base.py", line 1043, in render
    output = self.filter_expression.resolve(context)
  File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/template/base.py", line 709, in resolve
    obj = self.var.resolve(context)
  File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/template/base.py", line 850, in resolve
    value = self._resolve_lookup(context)
  File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/template/base.py", line 891, in _resolve_lookup
    current = getattr(current, bit)
  File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/secretballot/__init__.py", line 43, in get_total
    return getattr(self, upvotes_name) - getattr(self, downvotes_name)
AttributeError: 'Problem' object has no attribute 'total_upvotes'

secretballot v.0.5.0
Django 1.9.5
Python 3

Clearing old votes

I've been using secretballot very happily for several years to run a 'windsurfer of the year' vote, this year I'm getting a few reports that some people are being told they have voted, when they haven't - since last year.

I have no means of knowing if someone else on the same IP address had already voted, it is possible but they claim that no one else voted from their location.

Is it possible that they are still blocked by having done last years vote? If so, is there a means of removing all the previous votes? (Or at least the old IP addresses from previous years).

I was checking the documentation for a management command or similar, but I couldn't see anything.

Thanks,

-Alastair

New logo for Secretballot

I wanted to contribute to secretballot. I designed a logo for it. If you like it, I'll send you files and pr.
is there anything you want ?

secretballot

New maintainer wanted

It has been years since I've had any need for this project, and I'd love to hand it over to someone that cares about it and wants to maintain it. If you're seeing this get in touch and I'd be glad to transfer. I have no plans to release any versions after 1.0.0 right now.

object has no attribute 'vote_total'

I think I must have implemented incorrectly but I cannot work out how to get vote_total, total_upvotes and total_downvotes. I'm adding an upvote or downvote through a JS ajax call.

javascript.

function projectVote(pk, value) {
    info = [];
    info[0] = value;  //1 is passed for upvote and -1 for downvote
    $.ajax({
        url : '/vote/project/' + pk + '/',
        type : 'POST',
        data : { info : info },
        success : function(json) {
            console.log(json);
            $("#upvotes_" + pk.toString()).text(json.upvotes);
            $("#downvotes_" + pk.toString()).text(json.downvotes);
        },
        error : function(xhr,errmsg,err) {
            console.log(xhr.status + ": " + xhr.responseText); // provide a bit more info about the error to the console
        }
    })
}

It calls this view in views.py

def project_vote(request, pk):
    obj = Project.objects.get(pk=pk)
    info = request.POST.getlist('info[]')
    vote(request, Project, obj.id, int(info[0]))

    response_data = {
        'votes' : obj.vote_total,
        'upvotes' : obj.total_upvotes,
        'downvotes' : obj.total_downvotes,
    }
    return HttpResponse(
            json.dumps(response_data),
            content_type="application/json"
        )

I have enabled voting in apps.py

from django.apps import AppConfig
from django.apps import apps

class ProjectsConfig(AppConfig):
    name = 'projects'

    def ready (self):
        project_model = apps.get_model("projects", 'Project')
        secretballot.enable_voting_on(project_model)

With the ajax return I get 'Project' object has no attribute 'vote_total' so it is clearly failing when I define the response data. How do I access the votes. Please note, if I look at the database on the secretballot_vote table, I can see the vote.

Docs do not specify a migrate step

When I installed this I couldn't get it to work, as it was failing on an SQL error. After investigating I fixed the issue with a manage.py migrate which set up the necessary database tables.

This step isn't in the installation instructions, so should be added.

Middleware expects a user-agent

User-agent is not required, but middleware.py expects it. If the UA doesn't supply an agent it causes a runtime error. As this code is in middleware the whole app is affected.

On line 20:

s = ''.join((request.META['REMOTE_ADDR'], request.META['HTTP_USER_AGENT']))

would be better put as

s = ''.join((request.META['REMOTE_ADDR'], request.META.get('HTTP_USER_AGENT', '')))

Applications initialization error

This issue is related to the closed issue: #34

Secretballot currently throws the following error when trying django is trying initialize the applications before we are running initial migrations for a new dev project.

web_1  | django.db.utils.ProgrammingError: relation "django_content_type" does not exist
web_1  | LINE 1: ..."."app_label", "django_content_type"."model" FROM "django_co...

As mentioned in the previously closed issue this has to do with the ContentType call in __init__.py when enabling voting in a model in the ready() method of the AppConfig class.

Looking at the various solutions mentioned, we are currently importing and enable the voting all in the ready method, in accordance with django application loading: https://docs.djangoproject.com/en/2.1/ref/applications/#how-applications-are-loaded

class ProductConfig(AppConfig):
    name = 'products'

    def ready(self):
        import secretballot
        from .models import Product
        secretballot.enable_voting_on(Product, manager_name='objects')

This configuration still throws the same error as above.
Going in a adding the code below to the secretballot __init__.py will resolve this for initializing the django applications and running migrations, but it is not really a long term solution.

try:
    content_type = ContentType.objects.get_for_model(self.model).id
except:
    content_type = None

The current solution we are running is to change the order of the INSTALLED_APPS in django settings. Instead of following the django guidelines of having the order of local apps first, i.e. your local app should take precedence for overriding templates, static files, etc... Now to be able to run initial migrations django apps needs to be in the top of the INSTALLED_APPS which introduces a requirement of order.

INSTALLED_APPS = [
    # Django
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.postgres',
    # Local
    'product.apps.ProductsConfig',
    # Dist
    'secretballot',
]

Any thoughts on this and how it can be avoided?

Python: 3.5.6
Django version: 2.0.3

Thanks

Middleware - UnicodeDecodeError

There is a problem with unicode encoding of User-Agent.

class SecretBallotIpUseragentMiddleware(SecretBallotMiddleware):
    def generate_token(self, request):
        s = ''.join((request.META['REMOTE_ADDR'], request.META.get('HTTP_USER_AGENT', '')))
        return md5(s.encode('utf8')).hexdigest()

UnicodeDecodeError: 'ascii' codec can't decode byte ...

We should remove encode('utf-8')

Encoding error

Hello!
In class Vote(models.Model) you have:

def __str__(self): return '{} from {} on {}'.format(self.get_vote_display(), self.token, self.content_object)

Use, please u'{} from {} on {}' to correct utf-8 encoding, because you return self.content_object which can be in unicode.

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.