iris-hep / func_adl_xaod Goto Github PK
View Code? Open in Web Editor NEWClient interface to send a hierarchical SQL-like query to an xAOD backend
Client interface to send a hierarchical SQL-like query to an xAOD backend
The test error is quite odd. See the CI error: https://github.com/iris-hep/func_adl.xAOD/commit/e82166d8b20fa08057f5f507e4d28ba5d3374a31/checks?check_suite_id=351458433
This should get us to a better place when trying to properly pass exceptions up the line.
When looking at the output from this test:
def test_Aggregate_not_initial_const_SUM():
r = EventDataset("file://root.root") \
.Select("lambda e: e.Jets('AntiKt4EMTopoJets').Select(lambda j: j.pt()/1000).Sum()") \
.AsROOTTTree('dude.root', 'analysis', 'jetPT') \
.value(executor=exe_for_test)
lines = get_lines_of_code(r)
print_lines(lines)
l_sets = find_line_numbers_with("/1000", lines)
assert 2 == len(l_sets)
I saw that Sum was using an int - but j.pt() is a double. So shouldn't it be using a double to sum?
Should we support 2D arrays coming back? If so, put them in:
ele_mc_dr = good_eles.map(lambda e: mc_ele.map(lambda mc: 1.0))
Features and tests to do for this issue:
pandas
DFpandas
DF. See note below.For the user, it would have been nice to be able to implement the servicex array bomb (see above). However, one needs the full back-end machinery to understand the types the user is building. Current libraries are designed to have the full libraries only on the backend, not the front end. Thus... we can't make that decision. So we will have to punt on this feature for now.
The classes are C++ naming convention with "_" rather than "CppValue" and similar. These are internal classes so perhaps it doesn't matter as much, but still, shoudl do as we learn more about how to python.
That Marc wants to use this for performance:
If those work, then we are done with this issue. Past the proper quastle
text into this bug report when we have it. Once @mweinberg2718 verifies, we are done.
We have switched from slc6 to centos. And there are some hardcoded values in the source...
Mostly because the DeltaR
cut doesn't seem to be having an effect.
DEBUG:hep_tables.local:make_local expression: Call(func=Attribute(value=Call(func=Attribute(value=ast_Filter(expr=Call(func=Attribute(value=ast_DataFrame(), attr='Electrons', ctx=Load()), args=[Str(s='Electrons')], keywords=[]), filter=BoolOp(op=And(), values=[Compare(left=BinOp(left=Attribute(value=Call(func=Attribute(value=ast_DataFrame(), attr='Electrons', ctx=Load()), args=[Str(s='Electrons')], keywords=[]), attr='pt', ctx=Load()), op=Div(), right=Num(n=1000.0)), ops=[Gt()], comparators=[Num(n=20)]), Compare(left=Call(func=Attribute(value=Attribute(value=Call(func=Attribute(value=ast_DataFrame(), attr='Electrons', ctx=Load()), args=[Str(s='Electrons')], keywords=[]), attr='eta', ctx=Load()), attr='abs', ctx=Load()), args=[], keywords=[]), ops=[Lt()], comparators=[Num(n=1.5)])])), attr='map', ctx=Load()), args=[ast_Callable()], keywords=[]), attr='map', ctx=Load()), args=[ast_Callable()], keywords=[])
DEBUG:hep_tables.local:Stem sent to servicex:
EventSource
.Select(lambda e368: (e368.Electrons("Electrons"), e368))
.Select(lambda e416: (e416[0].Where(lambda e369: (((e369.pt() / 1000.0) > 20)) and (((abs(e369.eta())) < 1.5))), e416[1]))
.Select(lambda e417: e417[0].Select(lambda e381: e417[1].TruthParticles("TruthParticles").Where(lambda e409: (e409.pdgId() == 11)).Where(lambda e410: (((e410.pt() / 1000.0) > 20)) and (((abs(e410.eta())) < 1.5))).Where(lambda e411: (DeltaR(e381.eta(), e381.phi(), e411.eta(), e411.phi()) < 0.5))))
.Select(lambda e418: e418.Select(lambda e412: e412.Count()))
This is a big one - needed so that we can use ast-language as a backend for processing.
Use all the internal caching, etc., to create a local version of servicex - so it can run on docker, locally, with a local list of files.
Need to work with @mason to resolve this (see iris-hep/qastle#18).
When you preview it on a local machine from your dev envionrment, this looks just fine. WTF, man.
Make sure the query code does that correctly.
The following LINQ statement:
txt = translate_linq(f
.Select("lambda e1: e1.jets()")
.Select("lambda e7: e7.Select(lambda e2: e2.pt())")
.Select("lambda e4: e4.Select(lambda e3: e3 > 30.0).Where(lambda e5: e5)")
.Select("lambda e8: e8.Select(lambda e6: e6 / 1000.0)")
.AsROOTTTree("file.root", "treeme", ['col1']))
Fails to compile:
[ 33%] Building CXX object analysis/CMakeFiles/analysisLib.dir/Root/query.cxx.o
/home/atlas/rel/source/analysis/Root/query.cxx: In member function 'virtual StatusCode query::execute()':
/home/atlas/rel/source/analysis/Root/query.cxx:75:51: error: request for member 'pt' in '(i_obj71->xAOD::Electron_v1::<anonymous>.xAOD::Egamma_v1::pt() > 5.0e+4)', which is of non-
class type 'bool'
_col172.push_back((i_obj71->pt()>50000.0).pt());
There is an earlier warning that something is about to go very wrong, however:
192.168.46.93 - - [25/Mar/2020:18:13:05 +0000] "POST /servicex/generated-code HTTP/1.1" 200 5521 "-" "python-requests/2.22.0"
------> (call ResultTTree (call Select (call Select (call Select (call EventDataset (list 'localds://mc15_13TeV:mc15_13TeV.361106.PowhegPythia8EvtGen_AZNLOCTEQ6L1_Zee.merge.DAOD_ST
DM3.e3601_s2576_s2132_r6630_r6264_p2363_tid05630052_00')) (lambda (list e29) (call (attr e29 'Electrons') 'Electrons'))) (lambda (list e32) (call (attr (call (attr (call (attr e32
'Select') (lambda (list e30) (call (attr e30 'pt')))) 'Select') (lambda (list e31) (> e31 50000.0))) 'Where') (lambda (list e33) e33)))) (lambda (list e35) (call (attr e35 'Select'
) (lambda (list e34) (call (attr e34 'pt')))))) (list 'col1') 'treeme' 'file.root') [<_ast.Expr object at 0x7f11ac150b10>]
------> <func_adl_xAOD.backend.xAODlib.atlas_xaod_executor.atlas_xaod_executor object at 0x7f11ac13fc10>
Warning: assumping that the method 'xAOD::Electron.pt(...)' has return type 'double'. Use cpp_types.add_method_type_info to suppress (or correct) this warning.
Warning: assumping that the method 'xAOD::Electron.pt(...)' has return type 'double'. Use cpp_types.add_method_type_info to suppress (or correct) this warning.
Warning: assumping that the method 'bool.pt(...)' has return type 'double'. Use cpp_types.add_method_type_info to suppress (or correct) this warning.
The fact we are trying take pt
as a function on a bool
object!
This means making sure we use minio, etc., to download things.
New version of qastle
offers more completed rendering of the python ast
As a user I would like to be able to type "-11" and have it mean the negative of 11.
This will leave one out - invert. I'm not sure exactly what that should mean at this level. I'm going to make a decision, for now, to leave that to folks one level above that write the code and to take that out.
This is actually just adding a few simple things to the code and another node visitor and tests. So a minor update.
This drives the static type checkers nuts. Create a small single method that does this to drive down the number of errors. We are missing real errors because it is generating so many.
This: Warning: assumping that the method
should be going to the python logging system. Actually, should probably search for all print statements and move them there.
print
calls and make sure they are appropriate or should convert to loggetLogger
to get a named loggerDo the following:
The new qastle
supports this - make sure this is actually working!
When the qastle is shipped over to ServiceX this is just some place holder text right now. It would be nice in stack dumps and log messages to have the actual dataset name to aid with trackign and debugging when simultanious requests are in flight.
Perhaps we should make it so those warnings go away.
The use_servicex
uses some features from the backend
. This should not be the case.
[ ] Once fixed, make sure to update the electron example to remove the dependency.
The runner.sh
script needs to take arguments to control what it does. It should support the following scenarios:
filelist.txt
that is located somewhere.So, from the POV of arguments:
And then arguments for the file:
For testing this is going to need:
Should it? What sorts of things do we want it to point to? What protocols should we use?
Change the .
to a _
.
I'm suspicious because the filter function inside a Where statement isn't "visited" explicitly in the code. So we should make sure we have a test that covers this case.
The interface has totally changed - get the code into here.
namespace packages can't come from different sources - python's package discovery code fails.
See #3 (comment) for more info - double-check all version dependency references and make sure they conform. Including the func_adl
reference.
When I have 80 requests to process, I'd like them to get queued on the server right away.
Currently, it is one thread per request, which means only 40 things get requested. This is bad from at least two places:
Do this with just jet calibration. Once that works, close this issue. Then we have to open another issue to work on making this easy to use from the user's POV.
Currently installing from github. Need to replace that with something in pipy.
For example, already know pandas
is way out of date.
This code fails to build:
def build_ast_mark() -> ast.AST:
return EventDataset('file://root.root') \
.Select('lambda e: (e.Electrons("Electrons"), e.Muons("Muons"))') \
.Select('lambda e: (e[0].Select(lambda ele: ele.E()), e[0].Select(lambda ele: ele.pt()), e[0].Select(lambda e: e.phi(), e[0].Select(lambda e: e.eta()), e[1].Select(lambda mu: mu.E()), e[1].Select(lambda mu: mu.pt()), e[1].Select(lambda mu: mu.phi()), e[1].Select(lambda mu: mu.eta())))') \
.AsROOTTTree('dude.root', 'forkme', ['e_E', 'e_pt', 'e_phi', 'e_eta', 'mu_E', 'mu_pt', 'mu_phi', 'mu_eta']) \
.value(executor=do_exe)
Because that e
that we use for an electron isn't at the proper scope - it seems like it grabs the e
from one level up.
Turns out this line in our log files can sometimes generate over a minute delay:
xAOD::TFileAccessTracer INFO Sending file access statistics to http://rucio-lb-prod.cern.ch:18762/traces/
This is now noticeable in our running. Can we eliminate it?
Make sure the C++ generated from a Where
statement implement and
and or
correctly. I've seen some plots that make me think this is not what is happening.
However, as usual, it may be because I'm not sending the right code! Just be good to know there were tests for the logical operations!
The current only way in is async. We don't need that any longer with the underlying changes we've made in ServiceX_frontend. So propagate them through to the user.
We currently use analysisbase:latest
. But we've now seen that a change in the platform can introduce unexpected errors (see #21).
Query:
EventSource
.Select(lambda e353: (e353.Electrons("Electrons"), e353))
.Select(lambda e366: e366[0].Where(lambda e354: e366[1].TruthParticles("TruthParticles").Select(lambda e361: e361.Count()).Select(lambda e362: (e362 > 0))))
.Select(lambda e367: e367.Select(lambda e363: e363.pt()))
And the qastle code:
(call ResultTTree (call Select (call Select (call Select (call EventDataset (list 'localds://mc15_13TeV:mc15_13TeV.361106.PowhegPythia8EvtGen_AZNLOCTEQ6L1_Zee.merge.DAOD_STDM3.a0_s2576_s2132_r6630_r6264_p2363_tid05630052_00')) (lambda (list a1) (list (call (attr a1 'Electrons') 'Electrons') a1))) (lambda (list a2) (call (attr (subscript a2 0) 'Where') (lambda (list a3) (call (attr (call (attr (call (attr (subscript a2 1) 'TruthParticles') 'TruthParticles') 'Select') (lambda (list a4) (call (attr a4 'Count')))) 'Select') (lambda (list a5) (> a5 0))))))) (lambda (list a6) (call (attr a6 'Select') (lambda (list a7) (call (attr a7 'pt')))))) (list 'col1') 'treeme' 'file.root')
The error from the code generator:
(ServiceX_Exception(...), 'ServiceX rejected the transformation request: (400){\'message\': "Failed to submit transform request: Failed to generate translation code: Unable to generate a sequence from the given AST. Either there is an internal error, or you are trying to manipulate a \'cpp_value\' as a sequence (ast is: Name(id=\'arg_194\', ctx=Load()))"}')
And the log from the codgen container:
------> (call ResultTTree (call Select (call Select (call Select (call EventDataset (list 'localds://mc15_13TeV:mc15_13TeV.361106.PowhegPythia8EvtGen_AZNLOCTEQ6L1_Zee.merge.DAOD_STDM3.a0_s2576_s2132_r6630_r6264_p2363_tid05630052_00')) (lambda (
list a1) (list (call (attr a1 'Electrons') 'Electrons') a1))) (lambda (list a2) (call (attr (subscript a2 0) 'Where') (lambda (list a3) (call (attr (call (attr (call (attr (subscript a2 1) 'TruthParticles') 'TruthParticles') 'Select') (lambda (
list a4) (call (attr a4 'Count')))) 'Select') (lambda (list a5) (> a5 0))))))) (lambda (list a6) (call (attr a6 'Select') (lambda (list a7) (call (attr a7 'pt')))))) (list 'col1') 'treeme' 'file.root') [<_ast.Expr object at 0x7f10017bc8d0>]
------> <func_adl_xAOD.backend.xAODlib.atlas_xaod_executor.atlas_xaod_executor object at 0x7f100117a190>
Unable to generate a sequence from the given AST. Either there is an internal error, or you are trying to manipulate a 'cpp_value' as a sequence (ast is: Name(id='arg_194', ctx=Load()))
Traceback (most recent call last):
File "/home/servicex/servicex/code_generator_service/generate_code.py", line 42, in post
zip_data = self.translator.translate_text_ast_to_zip(code)
File "/home/servicex/servicex/code_generator_service/ast_translator.py", line 114, in translate_text_ast_to_zip
r = self.get_generated_xAOD(a, tempdir)
File "/home/servicex/servicex/code_generator_service/ast_translator.py", line 84, in get_generated_xAOD
f_spec = exe.write_cpp_files(exe.apply_ast_transformations(a), query_file_path)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/atlas_xaod_executor.py", line 105, in write_cpp_files
result_rep = qv.get_rep(ast)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 175, in get_rep
self.generic_visit(node) if use_generic_visit else self.visit(node)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 144, in visit
r = FuncADLNodeVisitor.visit(self, node)
File "/usr/local/lib/python3.7/ast.py", line 271, in visit
return visitor(node)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 520, in visit_Call
r = FuncADLNodeVisitor.visit_Call(self, call_node)
File "/usr/local/lib/python3.7/site-packages/func_adl/ast/func_adl_ast_utils.py", line 78, in visit_Call
return visitor(node, args)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 685, in call_ResultTTree
self.generic_visit(source)
File "/usr/local/lib/python3.7/ast.py", line 279, in generic_visit
self.visit(item)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 144, in visit
r = FuncADLNodeVisitor.visit(self, node)
File "/usr/local/lib/python3.7/ast.py", line 271, in visit
return visitor(node)
File "/usr/local/lib/python3.7/ast.py", line 281, in generic_visit
self.visit(value)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 144, in visit
r = FuncADLNodeVisitor.visit(self, node)
File "/usr/local/lib/python3.7/ast.py", line 271, in visit
return visitor(node)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 520, in visit_Call
r = FuncADLNodeVisitor.visit_Call(self, call_node)
File "/usr/local/lib/python3.7/site-packages/func_adl/ast/func_adl_ast_utils.py", line 78, in visit_Call
return visitor(node, args)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 802, in call_Select
seq = self.as_sequence(source)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 237, in as_sequence
rep = self.get_rep(generation_ast)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 175, in get_rep
self.generic_visit(node) if use_generic_visit else self.visit(node)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 144, in visit
r = FuncADLNodeVisitor.visit(self, node)
File "/usr/local/lib/python3.7/ast.py", line 271, in visit
return visitor(node)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 520, in visit_Call
r = FuncADLNodeVisitor.visit_Call(self, call_node)
File "/usr/local/lib/python3.7/site-packages/func_adl/ast/func_adl_ast_utils.py", line 78, in visit_Call
return visitor(node, args)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 859, in call_Where
rep = self.get_rep(c)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 175, in get_rep
self.generic_visit(node) if use_generic_visit else self.visit(node)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 144, in visit
r = FuncADLNodeVisitor.visit(self, node)
File "/usr/local/lib/python3.7/ast.py", line 271, in visit
return visitor(node)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 511, in visit_Call
self.visit_Call_Lambda(call_node)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 265, in visit_Call_Lambda
call_node.rep = self.get_rep(call_node.func.body)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 175, in get_rep
self.generic_visit(node) if use_generic_visit else self.visit(node)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 144, in visit
r = FuncADLNodeVisitor.visit(self, node)
File "/usr/local/lib/python3.7/ast.py", line 271, in visit
return visitor(node)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 520, in visit_Call
r = FuncADLNodeVisitor.visit_Call(self, call_node)
File "/usr/local/lib/python3.7/site-packages/func_adl/ast/func_adl_ast_utils.py", line 78, in visit_Call
return visitor(node, args)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 807, in call_Select
new_sequence_value = self.get_rep(c)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 175, in get_rep
self.generic_visit(node) if use_generic_visit else self.visit(node)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 144, in visit
r = FuncADLNodeVisitor.visit(self, node)
File "/usr/local/lib/python3.7/ast.py", line 271, in visit
return visitor(node)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 511, in visit_Call
self.visit_Call_Lambda(call_node)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 265, in visit_Call_Lambda
call_node.rep = self.get_rep(call_node.func.body)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 175, in get_rep
self.generic_visit(node) if use_generic_visit else self.visit(node)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 144, in visit
r = FuncADLNodeVisitor.visit(self, node)
File "/usr/local/lib/python3.7/ast.py", line 271, in visit
return visitor(node)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 626, in visit_Compare
left = self.get_rep(node.left)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 175, in get_rep
self.generic_visit(node) if use_generic_visit else self.visit(node)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 144, in visit
r = FuncADLNodeVisitor.visit(self, node)
File "/usr/local/lib/python3.7/ast.py", line 271, in visit
return visitor(node)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 520, in visit_Call
r = FuncADLNodeVisitor.visit_Call(self, call_node)
File "/usr/local/lib/python3.7/site-packages/func_adl/ast/func_adl_ast_utils.py", line 78, in visit_Call
return visitor(node, args)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 455, in call_Aggregate
return self.visit_call_Aggregate_initial(node, args)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 353, in visit_call_Aggregate_initial
seq = self.as_sequence(raw_seq)
File "/usr/local/lib/python3.7/site-packages/func_adl_xAOD/backend/xAODlib/ast_to_cpp_translator.py", line 255, in as_sequence
raise BaseException(f"Unable to generate a sequence from the given AST. Either there is an internal error, or you are trying to manipulate a '{type(rep).__name__}' as a sequence (ast is: {ast.dump(generation_ast)})")
BaseException: Unable to generate a sequence from the given AST. Either there is an internal error, or you are trying to manipulate a 'cpp_value' as a sequence (ast is: Name(id='arg_194', ctx=Load()))
192.168.21.58 - - [13/Apr/2020:21:46:09 +0000] "POST /servicex/generated-code HTTP/1.1" 500 201 "-" "python-requests/2.23.0"
See iris-hep/func_adl#4 for how to do it.
As a user, there are times I would like to force the backend to re-run everything. This is particularly helpful when trying to understand some behavior issues with the servicex
backend.
This is for the servicex
backend only. It requires just a simple additional option, which has to be passed all the way through to the servicex front end.
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.