vingtcinq / python-mailchimp Goto Github PK
View Code? Open in Web Editor NEWPython client for v3 of MailChimp API
License: MIT License
Python client for v3 of MailChimp API
License: MIT License
last available package for python 3 is https://pypi.python.org/pypi/mailchimp3/1.0.12,
following versions are only for python 2 or it was planned?
I wonder why all()
in member.py only returns 10 members? The MC API Docs don't mention a restriction.
It's documented here:
This operation looks quite convenient because it's idempotent: it allows you to put a user in a list safely, regardless of whether the user was already in that list.
The API could be:
mailchimp.member.create_or_update(list_id, email, data)
The library would compute the hash per MailChimp's spec:
subscriber_hash = hashlib.md5(email.lower().encode()).hexdigest()
Hello,
First of all, thanks for this library.
I think it would be of great value to add handling of errors, I haven't seen anything regarding them in your README. I was using your library in Django and when the endpoint returns with an error, Django explodes in the library instead of handling it. This means I never get the JSON of error, therefore I can never give a comprehensive message.
Here is my code example:
from django.core.validators import validate_email
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _
from mailchimp3 import MailChimp
client = MailChimp('user', '<api_key>')
class SubscribeForm(forms.Form):
name = forms.CharField(
label=_('Your name'),
max_length=255,
widget=forms.TextInput(
attrs={
'class': 'wrapper subscribe_form_input',
'placeholder': _('Your name')
}
),
error_messages={
'required': _('Please enter your name')
}
)
last_name = forms.CharField(
label=_('Your last name'),
max_length=255,
widget=forms.TextInput(
attrs={
'class': 'wrapper subscribe_form_input',
'placeholder': _('Your last name')
}
),
error_messages={
'required': _('Please enter your last name')
}
)
email = forms.EmailField(
label=_('Your email address'),
max_length=255,
widget=forms.TextInput(
attrs={
'class': 'wrapper subscribe_form_input',
'placeholder': _('Your email address')
}
),
error_messages={
'required': _('Please enter your email address'),
'invalid': _('Please enter a valid email address')
}
)
def clean(self):
form_data = self.cleaned_data
name = form_data.get('name', None)
last_name = form_data.get('last_name', None)
email = form_data.get('email', None)
if name and last_name and email:
try:
subscription = client.lists.members.create(
'<list_id>', {
'email_address': form_data['email'],
'status': 'pending',
'merge_fields': {
'FNAME': form_data['name'],
'LNAME': form_data['last_name'],
},
}
)
print subscription
except:
raise ValidationError(_(
"An error has occurred. " +
"This might be caused because you already " +
"have subscribed to our newsletter. " +
"If that's not the case, please try again."
))
If the library handles the error and manages to pass the JSON of the error to the developer, we could use it to show in a better way the reasons of errors.
Thanks for your great work and I hope this is helpful.
I'm getting error above when using client.campaigns.actions.send
API.
Traceback (most recent call last):
File "/backend/vinoia/vinoia/mailchimp/tests/test_helper.py", line 58, in test_send_email
result = self.send_email_from_campaign()
File "/backend/vinoia/vinoia/mailchimp/tests/test_helper.py", line 53, in send_email_from_campaign
return send_campaign(self.campaign_id)
File "/backend/vinoia/vinoia/mailchimp/helper.py", line 54, in send_campaign
return client.campaigns.actions.send(campaign_id)
File "/denv/lib/python3.4/site-packages/mailchimp3/entities/campaignactions.py", line 114, in send
return self._mc_client._post(url=self._build_path(campaign_id, 'actions/send'))
File "/denv/lib/python3.4/site-packages/mailchimp3/mailchimpclient.py", line 25, in wrapper
return fn(self, *args, **kwargs)
File "/denv/lib/python3.4/site-packages/mailchimp3/mailchimpclient.py", line 72, in _post
return r.json()
File "/denv/lib/python3.4/site-packages/requests/models.py", line 826, in json
return complexjson.loads(self.text, **kwargs)
File "/usr/lib/python3.4/json/__init__.py", line 318, in loads
return _default_decoder.decode(s)
File "/usr/lib/python3.4/json/decoder.py", line 343, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib/python3.4/json/decoder.py", line 361, in raw_decode
raise ValueError(errmsg("Expecting value", s, err.value)) from None
ValueError: Expecting value: line 1 column 1 (char 0)
Looks like response data from mailchimp
is not json
format.
#python3, #mailchimpv3.
On entities/campaigns.py line 174
if 'reply_to' not in data['setting']:
supposed to be
if 'reply_to' not in data['settings']:
As for Mailchimp documentation we can make up to 10 simultaneous connections to the API.
It can be pretty useful to create 10 separates threads to speed up time of retrieving large datasets.
As a benchmark, retrieving 23 000 contacts takes 235 seconds by batch of 5000.
With this method it could roughly takes 23 seconds.
Hi,
The schedule campaign interface seems not work quite happily with the datetime, as it throws below error
TypeError: datetime.datetime(xxxxx) is not JSON serializable
Indeed the datetime.datetime obj is not JSON serializable. I think may be cast it into string in the end will be better. Add below line to file entities/campaignactions.py line 102. I'm not quite sure what the '+00:00' means and I just follow the http://developer.mailchimp.com/documentation/mailchimp/reference/campaigns/#action-post_campaigns_campaign_id_actions_schedule
data['schedule_time'] = data['schedule_time'].strftime("%Y-%m-%dT%H:%M:00+00:00")
Hope this can help.
In MailChimpClient._post() raise HTTPError(r.json())
is called in this form.
In this way when we catch that exception can't parse it to python data structure.
If it was raise HTTPError(r.content)
we could use json.loads() to load that data.
Do you have any documentation on how to implement batch operations with your wrapper.
I'm trying to create (push) new members to an existing list.
client = MailChimp('wsjtest', '0c3c8df32f69c29f0d696200ddadccdb-us13')
user_list = [{'email_address': '[email protected]', 'status':'subscribe'}, {'email_address': '[email protected]', 'status':'subscribe'}, {'email_address': '[email protected]', 'status':'subscribe'}]
list_id = '15602234bb'
sample= {}
final_array = []
for user in user_list:
sample['method'] = "PUT"
sample['email_address'] = user['email_address']
sample['path'] = "lists/257561/members"
final_array.append(sample)
print final_array
client.member.create(list_id, {
"operations": final_array})
Is it that the api call of .create is expecting just one data object and not an array of dictionaries, that have all my user data in dictionaries?
In file entities/campaignactions.py line 97, it seems the the method utcoffset takes one argument.
if data['schedule_time'].tzinfo.utcoffset() != timedelta(0):
In my case I convert the local datetime to utc as below, is this the right way to do it?
datetime.utcfromtimestamp(local_time.timestamp()).replace(tzinfo=datetime.timezone.utc)
Thanks!
entities contains folder.py but init.py does not actually use the Folder class so it is not currently accessible.
The "status" value is required by the function, but is not required by the Mailchimp API.
In my use case, I need to be able to update members' data without overwriting their status. The Mailchimp api allows the handy "status_if_new" parameter, which will update all other given fields and merge tags for a member without overwriting status.
I understand the reasoning for requiring "status" (the API call does nothing for a new user without it), but it breaks my use case. Instead, you could require either "status" or "status_if_new", or just drop the requirement entirely.
I can create a PR for either version. Which do you think is better? I think requiring just one of them is best.
I am a derp and did a bunch of try except garbage for 2.0.0 when I should have just been checking if x in y. Changing to that format will be much cleaner and probably remove the kludgy use of six and sys that was recently added
Some MailChimp data that used to live in the response body now lives in the response headers, for instance the web_id
of a campaign. I need this data but it does not appear that it's available using this package. Is it or will it be possible to expose the response object or at least the response headers in question?
I don't want to sound mean or demanding or anything, just sharing some constructive feedback.
Unfortunately I wasn't able to use this library at all, and it is a shame :(
I am not even able to create a campaign and I don't know what I am doing wrong.
In [27]: client.campaign.create(data={"recipients":{"list_id":"3c307a9f3f"},"type":"regular","settings":{"subject_line":"Your Purchase Receipt","reply
...: _to":"[email protected]","from_name":"Customer Service"}})
---------------------------------------------------------------------------
HTTPError Traceback (most recent call last)
<ipython-input-27-88505da45a16> in <module>()
----> 1 client.campaign.create(data={"recipients":{"list_id":"3c307a9f3f"},"type":"regular","settings":{"subject_line":"Your Purchase Receipt","reply_to":"[email protected]","from_name":"Customer Service"}})
/usr/local/lib/python2.7/dist-packages/mailchimp3/entities/campaign.pyc in create(self, data)
22
23 def create(self, data):
---> 24 return self._mc_client._post(url=self.endpoint, data=data)
25
26 def patch(self, campaign_id, data):
/usr/local/lib/python2.7/dist-packages/mailchimp3/mailchimpclient.pyc in wrapper(self, *args, **kwargs)
23 def wrapper(self, *args, **kwargs):
24 if self.enabled:
---> 25 return fn(self, *args, **kwargs)
26 return wrapper
27
/usr/local/lib/python2.7/dist-packages/mailchimp3/mailchimpclient.pyc in _post(self, url, data)
57 return "{'status': 204}"
58 else:
---> 59 raise HTTPError(request=r)
60
61 @_enabled_or_noop
HTTPError:
What am I doing wrong here? Why it returns an error? How do I check what error I made?
Also, the version is not updated on pip.
It seems a reasonable wrapper but it is not usable without some form of feedback.
Please, take at least the time to update the version on pip or if you don't have time or interested (which is completely understandable), try to leave somewhere a looking for someone else to take charge.
Thanks anyway to your contribution to the open source.
Best,
S
I'm trying to create a member in a list but I'm getting the following error:
File "/usr/local/lib/python2.7/dist-packages/mailchimp3/entities/member.py", line 38, in create
return self._mc_client._post(url=self._build_path(list_id, 'members'), data=data)
File "/usr/local/lib/python2.7/dist-packages/mailchimp3/mailchimpclient.py", line 36, in _post
r = requests.post(url, auth=self.auth, json=data)
File "/usr/local/lib/python2.7/dist-packages/requests/api.py", line 88, in post
return request('post', url, data=data, *_kwargs)
File "/usr/local/lib/python2.7/dist-packages/requests/api.py", line 44, in request
return session.request(method=method, url=url, *_kwargs)
TypeError: request() got an unexpected keyword argument 'json'
This happens even if I take the example from the README, adjusting it for the list reference.
New to both the mailchimp API as well as python-mailchimp
, but I did some investigation on an issue I am having that leads me to think that perhaps something has changed in the API that python-mailchimp
wraps.
To start, I was getting an error trying to fetch the email addresses out of one of my mailchimp lists using one of the examples:
data = client.lists.members.all('<my-list-id>', fields="members.email_address,members.id", get_all=True)
with the following traceback:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/.../mailchimp3/entities/listmembers.py", line 96, in all
return self._iterate(url=self._build_path(list_id, 'members'), **queryparams)
File "/.../mailchimp3/baseapi.py", line 46, in _iterate
total = result['total_items']
KeyError: 'total_items'
This seemed plenty weird, so I read into the API (see: Read>Get information about members in a list and then decided to add "total_items"
:
res = client.lists.members.all('<my-list-id>', fields="members.email_address,members.id,total_items", get_all=True)
This resolved the KeyError
, but the behavior is still not as to be expected; with a list containing more than 100 members, the returned result only returns the last page of numbers. I believe the issue lies with merge_two_dicts
in helpers.py. The response JSON data is of the form: {'total_items': N, 'members': [{'email_address': '<address@domain>', 'id': '<hash-string>'}, ]}
. The merge_two_dicts
function does shallow copy that will simply overwrite the 'members'
key instead of append the lists. In other terms, this is the expected behavior of dict.update
:
>>> a = {'key': [1, 2, 3]}
>>> a.update({'key': [4, 5, 6]})
>>> print(a)
{'key': [4, 5, 6]}
Is this is due to a change in the API, or am I missing something else? If due to an API change, I haven't yet learned enough of mailchimp's documentation to be sure how to adjust to python-mailchimp
without potentially causing other troubles. I'll be looking into it and feedback on this would be great.
Update to match most recent changelog changes from 1/12/2017 and increment version number
If the subscriber exists, and i use: member.create method. It is return to me HTTPError which have no explanation.
Hi,
i get None in return when executing client.lists.members.delete(MAILCHIMP_LIST_ID, subscriber_hash). At the same time I can update are create members in this list without any problem. Was there a recent change in API?
Thanks,
Max
I got an HTTPError from a list.create (BTW why is this not lists.create?) with no explanation at all. Looking at the source, I can see that _post raises HTTPError(request=r) with r being the response and not the request (I suppose that's a bug). _get, _delete, and _patch/_put all do different things. This makes it really hard to code robustly against.
I don't know if some of this is due to MailChimp having an inconsistent API, but here are some suggestions:
That way, as a user of the library it would be easy to get started and debug what's wrong, and also easy to add error handling later (just slap a try: ... except requests.exceptions.RequestException as e: around the call).
In class TemplateDefaultContent is used bad endpoint. I used 'reports' instead 'templates'.
When i call api i have error:
INFO requests.packages.urllib3.connectionpool Starting new HTTPS connection (1): us14.api.mailchimp.com
DEBUG requests.packages.urllib3.connectionpool "GET /3.0/reports/TEMPLATE_ID/default-content HTTP/1.1" 404 168
*** HTTPError: 404 Client Error: Not Found for url: https://us14.api.mailchimp.com/3.0/reports/TEMPLATE_ID/default-content
Where 'TEMPLATE_ID' is some id
The Endpoint is supposed to have the list ID tacked on to the end, but it currently isn't, so this function is totally broken.
I'll create a PR shortly
json doesn't work with less
Now project has 1.0.21 version in setup.py
, but 1.0.17 on pypi and it's not easy to track commit which corresponds to each version. Think that adding versioning tags on github will help with this and make source installation easier (e.q. pip install -e git+git://github.com/charlesthk/[email protected]#egg=mailchimp3
)
pip package not updated to the latest. segment section is missing installing through pip
I'm trying to update the subscription status of a user with help of your nice little library and got into an issue:
MailChimp('username', 'key')
.member
.update('listID', 'userHash', {'status': 'unsubscribed'})
which results in following traceback:
File "/usr/local/lib/python2.7/dist-packages/mailchimp3/entities/member.py", line 29, in update
return self._mc_client._patch(url=self._build_path(list_id, 'members', member_id), data=data)
File "/usr/local/lib/python2.7/dist-packages/mailchimp3/mailchimpclient.py", line 25, in wrapper
return fn(self, *args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/mailchimp3/mailchimpclient.py", line 96, in _patch
r = requests.patch(url, auth=self.auth, json=data)
File "/usr/lib/python2.7/dist-packages/requests/api.py", line 110, in patch
return request('patch', url, data=data, **kwargs)
File "/usr/lib/python2.7/dist-packages/requests/api.py", line 44, in request
return session.request(method=method, url=url, **kwargs)
TypeError: request() got an unexpected keyword argument 'json'
Looking into Pythons requests patch
method shows:
def patch(url, data=None, **kwargs):
"""Sends a PATCH request.
:param url: URL for the new :class:`Request` object.
:param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`.
:param \*\*kwargs: Optional arguments that ``request`` takes.
:return: :class:`Response <Response>` object
:rtype: requests.Response
"""
return request('patch', url, data=data, **kwargs)
I think when you change requests.patch(url, auth=self.auth, json=data)
to requests.patch(url, auth=self.auth, data=data)
everything should work.
Maybe I'm wrong and dont see my fault, but this seems obvious.
Greetings!
I'm seeing some weird behavior when using requirements.txt vs when installing directly. Hoping you can shed some light on this.
Python 2.7.6
Django 1.6.11
When I install using requirements.txt like this:
sudo /usr/local/python/django/bin/pip install -r config/myvr/requirements.txt
The install fails and I see:
Collecting mailchimp3==2.0.3 (from -r config/myvr/requirements.txt (line 73))
2016-12-21 11:23:22,286 [salt.loaded.int.module.cmdmod][ERROR ][1759] stderr: /usr/local/python/django/local/lib/python2.7/site-packages/pip/req/req_f
ile.py:129: UserWarning: Disabling all use of wheels due to the use of --build-options / --global-options / --install-options.
cmdoptions.check_install_build_global(options, opts)
/usr/local/python/django/local/lib/python2.7/site-packages/pip/_vendor/requests/packages/urllib3/util/ssl_.py:90: InsecurePlatformWarning: A true SSLCon
text object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. For more informati
on, see https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning.
InsecurePlatformWarning
Could not find a version that satisfies the requirement mailchimp3==2.0.3 (from -r config/myvr/requirements.txt (line 73)) (from versions: )
No matching distribution found for mailchimp3==2.0.3 (from -r config/myvr/requirements.txt (line 73))
2016-12-21 11:23:22,286 [salt.loaded.int.module.cmdmod][ERROR ][1759] retcode: 1
However, when I install directly like this:
sudo /usr/local/python/django/bin/pip install mailchimp3==2.0.3
The install succeeds and I see:
(django)ubuntu@dev:~/myvr$ sudo /usr/local/python/django/bin/pip install mailchimp3==2.0.3
The directory '/home/ubuntu/.cache/pip/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
The directory '/home/ubuntu/.cache/pip' or its parent directory is not owned by the current user and caching wheels has been disabled. check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
Collecting mailchimp3==2.0.3
/usr/local/python/django/local/lib/python2.7/site-packages/pip/_vendor/requests/packages/urllib3/util/ssl_.py:318: SNIMissingWarning: An HTTPS request has been made, but the SNI (Subject Name Indication) extension to TLS is not available on this platform. This may cause the server to present an incorrect TLS certificate, which can cause validation failures. You can upgrade to a newer version of Python to solve this. For more information, see https://urllib3.readthedocs.io/en/latest/security.html#snimissingwarning.
SNIMissingWarning
/usr/local/python/django/local/lib/python2.7/site-packages/pip/_vendor/requests/packages/urllib3/util/ssl_.py:122: InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. You can upgrade to a newer version of Python to solve this. For more information, see https://urllib3.readthedocs.io/en/latest/security.html#insecureplatformwarning.
InsecurePlatformWarning
Downloading mailchimp3-2.0.3-py2.py3-none-any.whl (83kB)
100% |████████████████████████████████| 92kB 413kB/s
Requirement already satisfied: requests in /usr/local/python/django/lib/python2.7/site-packages (from mailchimp3==2.0.3)
Installing collected packages: mailchimp3
Successfully installed mailchimp3-2.0.3
(django)ubuntu@dev:~/myvr$
This must be installed using the requirements file and not installed directly for our production environment. Any chance you have an idea of what's up here?
Do you need any other information?
Hi
I try to subscribe without sending confirmation but not work:
client = MailChimp(base_settings.MAIL_CHIMP_ACCOUNT, base_settings.MAIL_CHIMP_APIKEY)
data= {
"email_address": "[email protected]",
"status": "subscribed",
"merge_fields": {
"FNAME": "Urist",
"LNAME": "McVankab"
}
}
member = client.member.create('xxxxxxxx',data)
#24 added member.create_or_update
, however, it expects the subscriber hash in argument instead of computing it from the email address.
This surprised me because I expected the library to deal with that sort of low level concerns.
There's a mailchimp3.helpers.get_subscriber_hash
function to compute this hash but it doesn't appear to be called anywhere. It was added in 344398b.
It's unclear to me whether it's a design decision or an oversight to have users perform hashing themselves. Perhaps someone who knows the history of this library could help?
Three courses of actions are possible at this point:
member_id
can be computed with get_subscriber_hash
member_id
is an email address and compute the hash automatically$[0-9a-f]{16}$
, use it as is; if it contains an @
assume it's an email and hash it; if it's something else raise an exception.I'm happy to provide a patch for either of these options.
Some entities such as members truly return all entities when queried (thanks to issue #36 and the pull request there), but other entities such as lists still only pull the first 10 entities. If possible, please update all endpoints so that they use the same behavior in this regard. I will start working on a PR if I have time to resolve this, but I didn't see it mentioned that it was still an issue here.
Currently python-mailchimp contains code like this in various methods:
class ListMembers(BaseApi):
def create(self, list_id, data):
# ...
response = self._mc_client._post(url=self._build_path(list_id, 'members'), data=data)
self.subscriber_hash = response['id']
return response
Unfortunately, when enabled=False
, this fails because self._mc_client._post
returns None
:
> self.subscriber_hash = response['id']
E TypeError: 'NoneType' object is not subscriptable
I think self.subscriber_hash = response['id'] if response else None
would do the job.
@stephenross If you added this code in your recent refactor perhaps you have an opinion on this? Thanks!
Please see pull request #79
The current implementation (perhaps since version 2?) uses liberally the following pattern:
try:
test = data['client_secret']
except KeyError as error:
error.message += ' The authorized app must have a client_secret'
raise
Unfortunately error.message
was deprecated in Python 2.6 and removed in Python 3.
There is an issue with how MailChimp handles deletion of list members, in that they don't delete them from the list, they change the status to "". If you want to add that person back to the list, you have to use the PUT operation to update the list member (PATCH apparently doesn't work).
http://developer.mailchimp.com/documentation/mailchimp/reference/lists/members/#
Since the PUT operation allows add or update, it might make sense to use that consistently instead of POST for creating a list member?
This provides some convenience for users so as not to introduce extra dependency on wheel in development
See the MailChimp API changelog for info on the extra methods that need adding. Note to self, do this and make a PR.
os.path.join adds 'list\123\members' instead of 'list/123/members' on windows.
if i use client.lists how it's described in readme. i have:
AttributeError: 'MailChimp' object has no attribute 'lists'
I have a list of users (from my database) and want to insert them into Mailchimp list. Here is the code I initially used:
for user_data in data:
response = client.lists.members.create(list_id, obj)
After the 10th request I get Bad Request Error without any specifics, but I guess I exceeded the limits. I am wondering how can this be done in singe batch request. I couldn't find some batch request example online. It would be great if you can provide one. I looked at the create function inside batches.py and here is the data parameter description:
data = {
"operations": array*
[
{
"method": string* (Must be one of "GET", "POST", "PUT", or "PATCH")
"path": string*,
}
]
}
I don't really understand how to build this path parameter, I tried in a couple of ways but none of them worked for me.
Thanks in advance!
We became this error on client.member.all call, any idea?
Traceback (most recent call last): File "./mailchimp_sync.py", line 8, in <module> print client.member.all('1234') File "/scripts/mailchimp3/entities/member.py", line 17, in all return self._mc_client._get(url=self._build_path(list_id, 'members'), **queryparams) File "/scripts/mailchimp3/mailchimpclient.py", line 25, in wrapper return fn(self, *args, **kwargs) File "/scripts/mailchimp3/mailchimpclient.py", line 76, in _get r.raise_for_status() File "/usr/local/lib/python2.7/site-packages/requests/models.py", line 851, in raise_for_status raise HTTPError(http_error_msg, response=self) requests.exceptions.HTTPError: 404 Client Error: Not Found
Is this a bug e.g. client.campaign.all() returns only 10.
How to handle all of them?
I believe the following is a rather common use case:
It takes a few minutes to figure out the solution:
client = Mailchimp(...)
client.member.create('<list_id>', {
'email_address': '[email protected]',
'status': 'subscribed',
'merge_fields': {
'FNAME': 'John',
'LNAME': 'Doe',
},
})
The onboarding experience would be smoother if the README showed that example (or a similar one).
I hope this feedback helps!
merge_id key in merge fields response is not correct, should be merge_id not id
I am trying to send emails of a campaign trought client.campaign.send(campaing_id="some_id")
, but it gives me the error TypeError: request() got an unexpected keyword argument 'json'
I am missing something or this is a bug?
I had to look through the source. I had been assuming it was list.members or similar.
Also - as mentioned in #36 - a mention in the docs about 'count' and other kwargs would be useful.
The doc comments for all: "returns the first 10 subscriber lists in the account."
Is there a currently a way to retrieve all lists using this library?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.