Code Monkey home page Code Monkey logo

celery-types's Introduction

celery-types PyPI

Type stubs for celery related projects:

install

pip install celery-types

You'll also need to monkey patch Task so generic params can be provided:

from celery.app.task import Task
Task.__class_getitem__ = classmethod(lambda cls, *args, **kwargs: cls) # type: ignore[attr-defined]

dev

initial setup

# install poetry (https://python-poetry.org/docs/)
curl -sSL https://install.python-poetry.org | python3 -
# install node
# install yarn
npm install --global yarn

# install node dependencies
yarn

regular development

poetry config virtualenvs.in-project true
poetry install

# run formatting, linting, and typechecking
s/lint

# build and publish
poetry publish --build

related

celery-types's People

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

Watchers

 avatar  avatar  avatar  avatar

celery-types's Issues

No overload variant of "shared_task" matches argument

Hello,

I am facing this issue that I am not quite sure how to resolve
I have a simple function defined like:

@shared_task
def foo(*args:Any, **kwargs:Any)->None:
    ...
    return None

and I am getting the following error when running mypy on it.

tasks.py:86: error: No overload variant of "shared_task" matches argument type "Callable[[VarArg(Any), KwArg(Any)], None]"
tasks.py:86: note: Possible overload variants:
tasks.py:86: note:     def shared_task(*, name: str = ..., serializer: str = ..., bind: bool = ..., autoretry_for: Tuple[Type[Exception], ...] = ..., max_retries: int = ..., default_retry_delay: int = ..., acks_late: bool = ..., ignore_result: bool = ..., soft_time_limit: int = ..., time_limit: int = ..., base: None = ..., retry_kwargs: Dict[str, Any] = ..., retry_backoff: bool = ..., retry_backoff_max: int = ..., retry_jitter: bool = ..., typing: bool = ..., rate_limit: Optional[str] = ..., trail: bool = ..., send_events: bool = ..., store_errors_even_if_ignored: bool = ..., autoregister: bool = ..., track_started: bool = ..., acks_on_failure_or_timeout: bool = ..., reject_on_worker_lost: bool = ..., throws: Tuple[Type[Exception], ...] = ..., expires: Union[float, datetime, None] = ..., priority: Optional[int] = ..., resultrepr_maxsize: int = ..., request_stack: _LocalStack = ..., abstract: bool = ...) -> Callable[[Callable[..., Any]], Task]
tasks.py:86: note:     def [_T <: Task] shared_task(*, name: str = ..., serializer: str = ..., bind: bool = ..., autoretry_for: Tuple[Type[Exception], ...] = ..., max_retries: int = ..., default_retry_delay: int = ..., acks_late: bool = ..., ignore_result: bool = ..., soft_time_limit: int = ..., time_limit: int = ..., base: Type[_T], retry_kwargs: Dict[str, Any] = ..., retry_backoff: bool = ..., retry_backoff_max: int = ..., retry_jitter: bool = ..., typing: bool = ..., rate_limit: Optional[str] = ..., trail: bool = ..., send_events: bool = ..., store_errors_even_if_ignored: bool = ..., autoregister: bool = ..., track_started: bool = ..., acks_on_failure_or_timeout: bool = ..., reject_on_worker_lost: bool = ..., throws: Tuple[Type[Exception], ...] = ..., expires: Union[float, datetime, None] = ..., priority: Optional[int] = ..., resultrepr_maxsize: int = ..., request_stack: _LocalStack = ..., abstract: bool = ...) -> Callable[[Callable[..., Any]], _T]

I am actually using args and kwargs, so removing those won't solve my issue.
Thanks in advance for help,

Loic

TaskRegistry has no type information for the register() method

I define a couple task classes, then attempt to register them in my tasks.py file (on app finalize):

registry: TaskRegistry = celery_app.tasks
registry.register(PullTaskRunner)
registry.register(PushTaskRunner)

However the type information seems to be missing the register method:

run run-test: commands[1] | mypy .
...
parameters/tasks.py:21: error: "TaskRegistry" has no attribute "register"
parameters/tasks.py:22: error: "TaskRegistry" has no attribute "register"

There is a method for it though:

class TaskRegistry(dict):
    """Map of registered tasks."""
    ...
    def register(self, task):
        """Register a task in the task registry.

        The task will be automatically instantiated if not already an
        instance. Name must be configured prior to registration.
        """
        ...

Add examples

Hi,

It would be great with some examples for both server and client side code (client with no access to server implementation, i.e. defined via celery.signature).

Currently I'm doing something like this client side

from celery import Signature, Celery

class WorkerClient(object):
    def __init__(self):
        self.app = Celery()

    def handle_request(self, a: int, b: int, task_id=None):
        sig: Signature[int] = self.app.signature("handle_request")
        options = {}
        if task_id:
            options["task_id"] = task_id
        return sig.apply_async(kwargs=dict(a=a, b=b), **options)

But it's not that typesafe on inputs (just settings kwargs). Preferably I'd define the signature with something like this where both input and return type are given.

HandleRequest = Task[[int, int], int]

sig: Sig[HandleRequest] = self.app.signature("handle_request")

Not sure if it's possible or if there are any good indicators on how to type client side code

Celery.autodiscover_tasks packages param has incorrect type

Celery.autodiscover_tasks parameter packages is typed as packages: Optional[List[str]] but the implementation also allows it to be a Callable (docs), and mypy complains when a Callable is passed in
error: Argument 1 to "autodiscover_tasks" of "Celery" has incompatible type "Callable[[], List[str]]"; expected "Optional[List[str]]" [arg-type]

Argument "args" to "send_task" of "Celery" has incompatible type "Tuple[str, str, str]"; expected "Optional[Tuple[Any]]"

Hello,
i have tasks with multiple args but it seems that the type hints only accepts a single argument

Argument "args" to "send_task" of "Celery" has incompatible type "Tuple[str, str, str]"; expected "Optional[Tuple[Any]]"

the provided type annotation is:

    def send_task(
        self,
        name: str,
        args: Optional[Tuple[Any]] = ...,
[...]

maybe that it should be

        args: Optional[Tuple[Any, ...]] = ...,

to allow for args of any length?

error: "Celery" has no attribute "on_after_configure"

Typechecking for this example doesn't work:

from celery import Celery
from celery.schedules import crontab

app = Celery()

@app.on_after_configure.connect
def setup_periodic_tasks(sender, **kwargs):
    # Calls test('hello') every 10 seconds.
    sender.add_periodic_task(10.0, test.s('hello'), name='add every 10')

    # Calls test('world') every 30 seconds
    sender.add_periodic_task(30.0, test.s('world'), expires=10)

    # Executes every Monday morning at 7:30 a.m.
    sender.add_periodic_task(
        crontab(hour=7, minute=30, day_of_week=1),
        test.s('Happy Mondays!'),
    )

@app.task
def test(arg):
    print(arg)

@app.task
def add(x, y):
    z = x + y
    print(z)
error: "Celery" has no attribute "on_after_configure"

Probably the other signals don't work as well

`Task.request` is not `celery.worker.request.Request` (during `task_prerun`)

Task.request is typed like below

@property
def request(self) -> Request: ...

With the following task_prerun receiver

@signals.task_prerun.connect
def task_prerun_receiver(*args: Any, **kwargs: Any) -> None:
    task: Task = kwargs["sender"]
    ...
    logger.info("task_prerun_receiver", task_request_dict=task.request.request_dict)

I'm getting at traceback like

Traceback (most recent call last):
  File "/app/venv/lib/python3.10/site-packages/celery/utils/dispatch/signal.py", line 276, in send
    response = receiver(signal=self, sender=sender, **named)
  File "/app/src/myapp/celery/app.py", line 59, in task_prerun_receiver
    logger.info("task_prerun_receiver", task_request_dict=task.request.request_dict)
AttributeError: 'Context' object has no attribute 'request_dict'

Celery documents "Sender is the task object being executed"
Ref: https://docs.celeryq.dev/en/stable/userguide/signals.html#task-prerun

I thought task.request was a Request object, but at least in the case of a receiver on task_prerun it's rather an instance of celery.app.task.Context.

Signature apply and apply_async are incorrect

I may be wrong, but I'm under the impression that Signature.apply and Signature.apply_async are wrongly typed.

args: Optional[Tuple[Any]] = ...,

args: Optional[Tuple[Any]] = ...,

They should be

-       args: Optional[Tuple[Any]] = ...,
+       args: Optional[Tuple[Any, ...]] = ...,

Otherwise, we could have only one positional arg. Moreover, the other args in this file are correctly typed.

I'll open a PR soon.

Signature for group method may be incorrect?

I am creating a group using a generator of task signatures:

    job = group(
        resolve_value.s(value.id, as_of, http_meta)
        for value, as_of in work.items()
    )

This is valid according to the celery source comments:

https://github.com/celery/celery/blob/master/celery/canvas.py#L1009-L1012

Note:
    If only one argument is passed, and that argument is an iterable
    then that'll be used as the list of tasks instead: this
    allows us to use ``group`` with generator expressions.

However mypy is complaining:

value_query.py:150: error: Argument 1 to "group" has incompatible type "Generator[Signature, None, None]"; expected "Signature"

All my tests pass however, so it appears the type declaration is not complete here.
Here's how Visual Code sees it:

image

New release?

Hi @sbdchd, any chance we could get a release out within the next few weeks?

It would be great to have the latest fixes in a released version. Let me know if there is anything I can do to help.

task_cls

Hi there. I'm working with a repository where we've overridden the default task class and added some methods, and we're using task_cls to initialize Celery with this as the default class. I'm seeing lots of errors about these custom methods not existing, and I think this is because celery-types doesn't support task_cls.

Is this something you'd be open to supporting in the future?

Fix poetry build setup

Currently using the latest poetry breaks the build of the wheel

❯ tree celery_types-0.8.2-py3-none-any        
celery_types-0.8.2-py3-none-any
├── amqp-stubs
│   ├── __init__.pyi
│   └── exceptions.pyi
├── billiard-stubs
│   ├── __init__.pyi
│   ├── einfo.pyi
│   └── exceptions.pyi
├── celery-stubs
│   ├── __init__.pyi
│   ├── _state.pyi
│   ├── app
│   │   ├── __init__.pyi
│   │   ├── amqp.pyi
│   │   ├── base.pyi
│   │   ├── beat.pyi
│   │   ├── control.pyi
│   │   ├── events.pyi
│   │   ├── log.pyi
│   │   ├── registry.pyi
│   │   ├── routes.pyi
│   │   ├── task.pyi
│   │   └── utils.pyi
│   ├── apps
│   │   ├── __init__.pyi
│   │   └── worker.pyi
│   ├── backends
│   │   ├── __init__.pyi
│   │   └── base.pyi
│   ├── canvas.pyi
│   ├── concurrency
│   │   ├── __init__.pyi
│   │   └── base.pyi
│   ├── exceptions.pyi
│   ├── loaders
│   │   ├── __init__.pyi
│   │   └── base.pyi
│   ├── local.pyi
│   ├── result.pyi
│   ├── schedules.pyi
│   ├── signals.pyi
│   ├── states.pyi
│   ├── utils
│   │   ├── __init__.pyi
│   │   ├── abstract.pyi
│   │   ├── collections.pyi
│   │   ├── dispatch
│   │   │   ├── __init__.pyi
│   │   │   └── signal.pyi
│   │   ├── graph.pyi
│   │   ├── log.pyi
│   │   ├── objects.pyi
│   │   ├── term.pyi
│   │   ├── threads.pyi
│   │   └── time.pyi
│   └── worker
│       ├── __init__.pyi
│       ├── request.pyi
│       └── worker.pyi
├── celery_types-0.8.2.dist-info
│   ├── LICENSE
│   ├── METADATA
│   ├── RECORD
│   └── WHEEL
├── django_celery_results-stubs
│   ├── __init__.pyi
│   ├── managers.pyi
│   └── models.pyi
├── ephem-stubs
│   └── __init__.pyi
├── kombu-stubs
│   ├── __init__.pyi
│   ├── abstract.pyi
│   ├── connection.pyi
│   ├── entity.pyi
│   ├── exceptions.pyi
│   ├── message.pyi
│   ├── messaging.pyi
│   ├── pidbox.pyi
│   ├── pools.pyi
│   ├── resource.pyi
│   ├── transport
│   │   ├── __init__.pyi
│   │   └── base.pyi
│   └── utils
│       ├── __init__.pyi
│       └── uuid.pyi
└── vine-stubs
    ├── __init__.pyi
    ├── abstract.pyi
    ├── funtools.pyi
    ├── promises.pyi
    └── synchronization.pyi

18 directories, 74 files
❯ tree celery_types-0.8.3-py3-none-any
celery_types-0.8.3-py3-none-any
├── celery_types-0.8.3.dist-info
│   ├── LICENSE
│   ├── METADATA
│   ├── RECORD
│   └── WHEEL
└── typings
    ├── amqp
    │   ├── __init__.pyi
    │   └── exceptions.pyi
    ├── billiard
    │   ├── __init__.pyi
    │   ├── einfo.pyi
    │   └── exceptions.pyi
    ├── celery
    │   ├── __init__.pyi
    │   ├── _state.pyi
    │   ├── app
    │   │   ├── __init__.pyi
    │   │   ├── amqp.pyi
    │   │   ├── base.pyi
    │   │   ├── beat.pyi
    │   │   ├── control.pyi
    │   │   ├── events.pyi
    │   │   ├── log.pyi
    │   │   ├── registry.pyi
    │   │   ├── routes.pyi
    │   │   ├── task.pyi
    │   │   └── utils.pyi
    │   ├── apps
    │   │   ├── __init__.pyi
    │   │   └── worker.pyi
    │   ├── backends
    │   │   ├── __init__.pyi
    │   │   └── base.pyi
    │   ├── canvas.pyi
    │   ├── concurrency
    │   │   ├── __init__.pyi
    │   │   └── base.pyi
    │   ├── exceptions.pyi
    │   ├── loaders
    │   │   ├── __init__.pyi
    │   │   └── base.pyi
    │   ├── local.pyi
    │   ├── result.pyi
    │   ├── schedules.pyi
    │   ├── signals.pyi
    │   ├── states.pyi
    │   ├── utils
    │   │   ├── __init__.pyi
    │   │   ├── abstract.pyi
    │   │   ├── collections.pyi
    │   │   ├── dispatch
    │   │   │   ├── __init__.pyi
    │   │   │   └── signal.pyi
    │   │   ├── graph.pyi
    │   │   ├── log.pyi
    │   │   ├── objects.pyi
    │   │   ├── term.pyi
    │   │   ├── threads.pyi
    │   │   └── time.pyi
    │   └── worker
    │       ├── __init__.pyi
    │       ├── request.pyi
    │       └── worker.pyi
    ├── django_celery_results
    │   ├── __init__.pyi
    │   ├── managers.pyi
    │   └── models.pyi
    ├── ephem
    │   └── __init__.pyi
    ├── kombu
    │   ├── __init__.pyi
    │   ├── abstract.pyi
    │   ├── connection.pyi
    │   ├── entity.pyi
    │   ├── exceptions.pyi
    │   ├── message.pyi
    │   ├── messaging.pyi
    │   ├── pidbox.pyi
    │   ├── pools.pyi
    │   ├── resource.pyi
    │   ├── transport
    │   │   ├── __init__.pyi
    │   │   └── base.pyi
    │   └── utils
    │       ├── __init__.pyi
    │       └── uuid.pyi
    └── vine
        ├── __init__.pyi
        ├── abstract.pyi
        ├── funtools.pyi
        ├── promises.pyi
        └── synchronization.pyi

19 directories, 74 files

0.8.3 regression

Hello,
just after the release of version 0.8.3 my nightly mypy CI build failed due to errors in celery typing

Once pinned celery-types to 0.8.2 everything back working

May it be some regression introduced in 0.8.3? It is seems that with the new version celery is no longer recognized as typed

error: Skipping analyzing "celery.result": found module but no type hints or library stubs
error: Skipping analyzing "celery.app.task": found module but no type hints or library stubs
error: Argument 1 to "xyz" becomes "Any" due to an unfollowed import
error: Skipping analyzing "celery": found module but no type hints or library stubs
error: Skipping analyzing "celery.exceptions": found module but no type hints or library stubs

Wrong type for Inspect class

Hi there,

Maybe it's the documentation of Celery that's unclear but for celery.app.control.Inspect the method stats say Ref:

Returns: Dictionary {HOSTNAME: STAT_INFO}.
Return type: Dict

But inside your code I see:

def stats(self) -> list[dict[str, _Reply]]: ...

I have the same issue with query_task.

If I follow the rabbit:

Inspect.stats(): return self._request('stats')
Inspect._request(...): return self._prepare(...)
And Inspect._prepare(...):

    def _prepare(self, reply):
        if reply:
            # flatten_reply convert [{"HOSTNAME": Reply}, {"HOSTNAME": Reply}, ...]
            # to {"HOSTNAME": Reply, "HOSTNAME": Reply, ...}
            # so list[dict[str, _Reply]] to dict[str, _Reply]
            by_node = flatten_reply(reply)
            if (self.destination and
                    not isinstance(self.destination, (list, tuple))):
                return by_node.get(self.destination)
            if self.pattern:
                pattern = self.pattern
                matcher = self.matcher
                # Return a dict[str, _Reply]
                return {node: reply for node, reply in by_node.items()
                        if match(node, pattern, matcher)}
            return by_node

Ref for Inspect._prepare

I'm pretty new with django, celery, etc (about a week old) so maybe I just miss something, thanks if someone can explain it to me it'll be more than welcome.

Incorrect typing for autoretry_for

We have the following code

@shared_task(
    autoretry_for=(PoolTimeout, CancelledError),
    max_retries=10,
    retry_backoff=True,
    retry_backoff_max=100,
    retry_jitter=False,
)
def my_task(...):
  ...

But unfortunately mypy it's throwing the following error:

error: Argument "autoretry_for" to "shared_task" has incompatible type "Tuple[Type[PoolTimeout], Type[CancelledError]]"; expected "Tuple[Type[Exception], ...]"  [arg-type]

The reason for this is that CancelledError extends from BaseException instead of Exception. This is the issue where they changed the base class.

TypeError: 'type' object is not subscriptable

Hello!

I have a problem with the new Task annotations.
I installed version 0.13.0 and started receiving typing errors on Task annotations (from #75)

Missing type parameters for generic type "Task"

So added the expected annotations, like:

from celery.app.task import Task
from typing import Any

@app.task(bind=True)
def my_task(self: Task[Any, Any]):

But now celery (version 5.2.7) fails at runtime with:

    self: Task[Any, Any],
          │    │    └ typing.Any
          │    └ typing.Any
          └ <class 'celery.app.task.Task'>

TypeError: 'type' object is not subscriptable

What I'm missing? 😢

0.15.0 -> 0.17.0 error: "List[Dict[str, Any]]" has no attribute "items" [attr-defined]

Hi! Thanks for creating celery-types.

Since 0.17.0, the following type seems to be wrongly identified. The code below shows a working example. I'm guessing that inspect.active() just returns a dict.

def example(inspect: celery.app.control.Inspect):
    active = inspect.active()
    for _, tasks in active.items():   # error: List[Dict[str, Any]]" has no attribute "items"  [attr-defined] ## happens here
        print(task["type"])

Add support for DjangoTask's delay_on_commit and apply_async_on_commit methods

Celery 5.4 introduced some shortcuts for Django projects using a custom task class. This new DjangoTask base class adds the following methods:

  • delay_on_commit
  • apply_async_on_commit

https://docs.celeryq.dev/en/stable/django/first-steps-with-django.html#trigger-tasks-at-the-end-of-the-database-transaction

Not sure what's the best way to support app.task/shared_task returning instances of this base class but we can start by adding stubs for celery.contrib.django.task.DjangoTask (see API reference).

Split the package into small packages

👋 Hello, I am interested in the kombu stubs and nothing else.

From what I saw, there is no way to simply use the kombu typings, I need to download everything.

What are your thoughts on publishing each package individually and making the current repository an aggregation of the individual parts?

Mark stubs as `partial` per PEP-561

Please, consider marking these stubs as partial per PEP-561. Otherwise, Pylance, for example, reports all untyped imports as missing (try from celery.backends.database.models import TaskExtended).

Thank you 🙂

The args in this function declaration helped me catch an issue. I was using:

@celery.shared_task(
  exponential_backoff = 5
)
def some_func(...):

I thought exponential_backoff was a celery decorator param... turns out it's not! This python package is very helpful because now my type linter caught that issue. Thanks!

[Question] self annotation

How should I annotate celery when bind=True with self?

Solved by below answer by @sbdchd.

you can use type alias:

from typing import Any

from celery import Task

SelfTask = Task[Any, Any]


@app.task(bind=True)
def add_2(self: SelfTask, x: int, y: int) -> None:
    logger.info(self.request.id)

tags so other can find it:

celery type annotation task self

celery.signature should accept str

first of all, thank you for creating this package!

I have an issue with celery.signature not accepting str:

error: Argument 1 to "signature" has incompatible type "str"; expected "Union[Signature, Dict[str, Any]]"  [arg-type]

The celery documentation shows an example with str, https://docs.celeryproject.org/en/stable/userguide/canvas.html
Which contradicts the source code comments here: https://github.com/celery/celery/blob/5d72aeedb6329b609469c63998e9335e017bd204/celery/canvas.py#L1568

You can see that Signature which is called by signature supports str here: https://github.com/celery/celery/blob/5d72aeedb6329b609469c63998e9335e017bd204/celery/canvas.py#L149

Group is missing tasks

I noticed that canvas.group is using self.tasks a bit everywhere, but it's never declared in any __init__ (I might have missed it though).
And the stubs don't declare it either. That has the effect of triggering mypy when doing mygroup.tasks.

error: "group" has no attribute "tasks"  [attr-defined]

I'm not sure if this is supposed to be a stub-only fix (I could do it) or if it highlights a deeper potential bug, where we could have branches that would raise AttributeError (I'll need some help, and a ticket would be opened on celery repo).

Release schedule

Is there a release schedule/process for this project? When will merged branches be released to pypi?

Add types for `kombu.utils.json`

Hello,

Thanks for this collection of type stubs!

I've been using it in a project, and recently i've had to use kombu JSON serializers, and mypy is reporting error: Module "kombu.utils" has no attribute "json" [attr-defined] because the types for that module are missing.

Calling a chord object should return an AsyncResult

When you "call" a chord object, it delegates to apply_async, so the return value of something like

chord([task1.s(), task2.s()])(callback.s())

should be AsyncResult

I tried adding this:

    def __call__(
        self,
        body: Optional[Signature[Any]] = ...,
        **options: Any,
    ) -> celery.result.AsyncResult[Any]: ...

but mypy complains because this disagrees with Signature's typing:

typings/celery/canvas.pyi:376:5: error: Signature of "__call__" incompatible with supertype "Signature"  [override]
typings/celery/canvas.pyi:376:5: note:      Superclass:
typings/celery/canvas.pyi:376:5: note:          def __call__(self, *partial_args: Any, **partial_kwargs: Any) -> Any
typings/celery/canvas.pyi:376:5: note:      Subclass:
typings/celery/canvas.pyi:376:5: note:          def __call__(self, body: Optional[Signature[Any]] = ..., **options: Any) -> AsyncResult[Any]

is it possible to type this correctly?

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.