Coder Social home page Coder Social logo

rust-secure-code / cargo-supply-chain Goto Github PK

View Code? Open in Web Editor NEW
308.0 13.0 18.0 414 KB

Gather author, contributor and publisher data on crates in your dependency graph.

License: Apache License 2.0

Rust 100.00%
dependency-graph cargo-subcommand cargo

cargo-supply-chain's Introduction

cargo-supply-chain

Gather author, contributor and publisher data on crates in your dependency graph.

Use cases include:

  • Find people and groups worth supporting.
  • Identify risks in your dependency graph.
  • An analysis of all the contributors you implicitly trust by building their software. This might have both a sobering and humbling effect.

Sample output when run on itself: publishers, crates, json.

Usage

To install this tool, please run the following command:

cargo install cargo-supply-chain

Then run it with:

cargo supply-chain publishers

By default the supply chain is listed for all targets and default features only.

You can alter this behavior by passing --target=… to list dependencies for a specific target. You can use --all-features, --no-default-features, and --features=… to control feature selection.

Here's a list of subcommands:

Gather author, contributor and publisher data on crates in your dependency graph

Usage: COMMAND [ARG]…

Available options:
    -h, --help      Prints help information
    -v, --version   Prints version information

Available commands:
    publishers  List all crates.io publishers in the depedency graph
    crates      List all crates in dependency graph and crates.io publishers for each
    json        Like 'crates', but in JSON and with more fields for each publisher
    update      Download the latest daily dump from crates.io to speed up other commands

Most commands also accept flags controlling the features, targets, etc.
See 'cargo supply-chain <command> --help' for more information on a specific command.

License

Triple licensed under any of Apache-2.0, MIT, or zlib terms.

cargo-supply-chain's People

Contributors

blackholefox avatar heroickatora avatar nemo157 avatar owez avatar pacak avatar shnatsel avatar smoelius avatar ugandalf avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cargo-supply-chain's Issues

Deal with terminal control sequences in crates.io/Github usernames

We currently print data received from crates.io as-is to terminal. This means that if there are any terminal control sequences embedded in it, they will be printed as-is and potentially affect the terminal.

For example, embedding a carriage return might allow erasing a line from the output, which would allow hiding some dependencies!

We need to either ensure that either both crates.io and Github do not allow and will never allow characters from that range in any fields we print, or add an extra pass that escapes those control sequences.

Crate fetching is slow

I'm running a test run using the crates command and as I'm writing it's fetching crates. It seems to take quite a long time, even with a relatively low dependency crate such as cargo-supply-chain (only 79 deps listed), as seen here:

image

It would be useful and more functional if it fetched these in parallel, especially due to the high latency with the crates.io api.

Cache of crates.io data dumps should expire

Currently, all commands consider any data retrieved via cargo supply-chain update as valid.

This might silently leave you with very outdated data (#9 would provide a partial fix).

The usage should either be opt-in with an argument (--cached) or there should be some expiration policy. For example, we could consider the dumps outdated if they are older than one day and provide arguments to adjust this such that a duration of 0 ensures that no cache is used.

Use an argument parser

Right now we have basic hand-rolled argument parsing. While it was sufficient for a prototype, its limitations are starting to show.

The sales pitch for https://github.com/rust-cli/climake looks nice - it's zero-dependency, 100% safe and generates the help text.

Split argument validation into a separate function

Right now argument validation and actually calling the subcommands is lumped together in one function:

fn dispatch_command(args: Args) -> Result<(), std::io::Error> {
// FIXME: validating arguments and acting on them is lumped together in one function.
// This ugly and interferes with error handling and unit testing.

This makes them impossible to unit-test and necessitates manual calls to eprintln_help() in multiple places instead of just one in main on any validation error.

We should split argument validation to another function that accepts Args and returns Result<ValidatedArgs>, where ValidatedArgs is something like:

enum ValidatedArgs {
    Help {command: Option<String>},
    Update {cache_max_age: Duration},
    Crates {cache_max_age: Duration, metadata_args: Vec<String>},
    Publishers {cache_max_age: Duration, metadata_args: Vec<String>},
}

And make dispatch_command accept that as an argument.

Provide a way to filter out crates

For rustc itself, supply-chain shows the following crates as dependencies:

270. rustc-ap-rustc_arena: alexcrichton
271. rustc-ap-rustc_ast: alexcrichton
272. rustc-ap-rustc_ast_passes: alexcrichton
273. rustc-ap-rustc_ast_pretty: alexcrichton
274. rustc-ap-rustc_attr: alexcrichton
275. rustc-ap-rustc_expand: alexcrichton
276. rustc-ap-rustc_feature: alexcrichton
277. rustc-ap-rustc_fs_util: alexcrichton
278. rustc-ap-rustc_graphviz: alexcrichton
279. rustc-ap-rustc_index: alexcrichton
280. rustc-ap-rustc_lexer: alexcrichton
281. rustc-ap-rustc_macros: alexcrichton
282. rustc-ap-rustc_parse: alexcrichton
283. rustc-ap-rustc_serialize: alexcrichton
284. rustc-ap-rustc_session: alexcrichton
285. rustc-ap-rustc_span: alexcrichton

But none of these are actually dependencies - these are the rustc crates themselves, just with a different name. So they should be ignored as if they were in-tree. cargo-supply-chain has no way of knowing these are the same crate, so it would be nice to have a way to tell it.

Possibly this should be a feature request for cargo metadata instead?

Create git tags for releases

In ad36857, the test data is excluded from the crate. Previously nixpkgs was using cargo-supply-chain from crates.io since the github repository doesn't tag the releases. We now have to disable some of the tests due to the missing assets when I was trying to update the package. It would be nice if releases are tagged on github, so we can keep the tests enabled

Cancelling `cargo supply-chain update` leaves it believing it is up to date

I ran cargo supply-chain update, then realised I should probably check if there was an update to the tool itself first so ctrl+ced the update. When I then ran cargo supply-chain crates it thinks that it has an up to date cache, but then has to individually fetch the data, and attempting to update again does nothing:

> cargo supply-chain crates
...
Using cached data. Cache age: 18h 33m 14s 126ms 57us 170ns
Fetching data for "ansi_term" (1/91)
Fetching data for "anyhow" (2/91)

> cargo supply-chain update
Note: this will download large amounts of data (approximately 250Mb).
On a slow network this will take a while.
No updates found

I had to then force an update with cargo supply-chain update --cache-max-age 1s.

Reject arguments that don't make sense for `update` subcommand

Currently cargo supply-chain does not error out when called like this:

cargo supply-chain update --diffable -- --filter-platform=x86_64-unknown-linux-gnu

which is a rather nonsensical set of arguments, since neither --diffable nor the cargo-metadata arguments are applicable in this context: we have no useful output to diff and we never call cargo metadata from the update subcommand.

Strict `CFLAGS` break the build

This is probably really a ring bug. (Or, WontFix, if I am too weird.) Let me know if you think I should file it there, too.

I use weird CFLAGS because I am a weirdo:

~/src/rust/cargo-supply-chain % echo $CFLAGS
-Weverything -Werror -O0 -std=c11

I'm on macOS with clang:

~/src/rust/cargo-supply-chain % clang --version
Apple clang version 12.0.0 (clang-1200.0.32.29)
Target: x86_64-apple-darwin20.3.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

I leave them in my standard shell environment just to enjoy the explosions. Here's how ring explodes:

error: failed to run custom build command for `ring v0.16.20`

Caused by:
  process didn't exit successfully: `/Users/chris/src/rust/cargo-supply-chain/target/debug/build/ring-f05a2e2ad93a365a/build-script-build` (exit code: 101)
  --- stdout
  OPT_LEVEL = Some("0")
  TARGET = Some("x86_64-apple-darwin")
  HOST = Some("x86_64-apple-darwin")
  CC_x86_64-apple-darwin = None
  CC_x86_64_apple_darwin = None
  HOST_CC = None
  CC = Some("clang")
  CFLAGS_x86_64-apple-darwin = None
  CFLAGS_x86_64_apple_darwin = None
  HOST_CFLAGS = None
  CFLAGS = Some("-Weverything -Werror -O0 -std=c11")
  CRATE_CC_NO_DEFAULTS = None
  DEBUG = Some("true")

  --- stderr
  running "clang" "-O0" "-ffunction-sections" "-fdata-sections" "-fPIC" "-g" "-fno-omit-frame-pointer" "--target=x86_64-apple-darwin" "-Weverything" "-Werror" "-O0" "-std=c11" "-I" "include" "-pedantic" "-pedantic-errors" "-Wall" "-Wextra" "-Wcast-align" "-Wcast-qual" "-Wconversion" "-Wenum-compare" "-Wfloat-equal" "-Wformat=2" "-Winline" "-Winvalid-pch" "-Wmissing-field-initializers" "-Wmissing-include-dirs" "-Wredundant-decls" "-Wshadow" "-Wsign-compare" "-Wsign-conversion" "-Wundef" "-Wuninitialized" "-Wwrite-strings" "-fno-strict-aliasing" "-fvisibility=hidden" "-fstack-protector" "-gfull" "-DNDEBUG" "-c" "-o/Users/chris/src/rust/cargo-supply-chain/target/debug/build/ring-7381a064665e3f2d/out/aesni-x86_64-macosx.o" "/Users/chris/.cargo/registry/src/github.com-1ecc6299db9ec823/ring-0.16.20/pregenerated/aesni-x86_64-macosx.S"
  error: include location '/usr/local/include' is unsafe for cross-compilation [-Werror,-Wpoison-system-directories]
  <built-in>:93:9: error: macro is not used [-Werror,-Wunused-macros]
  #define __SIG_ATOMIC_MAX__ 2147483647
          ^
  <built-in>:343:9: error: macro is not used [-Werror,-Wunused-macros]
  #define __SSE2_MATH__ 1
          ^
  <built-in>:341:9: error: macro is not used [-Werror,-Wunused-macros]
  #define __SSE3__ 1
          ^
  <built-in>:305:9: error: macro is not used [-Werror,-Wunused-macros]
  #define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
          ^
  <built-in>:342:9: error: macro is not used [-Werror,-Wunused-macros]
  #define __SSE2__ 1
          ^
  <built-in>:94:9: error: macro is not used [-Werror,-Wunused-macros]
  #define __CHAR16_TYPE__ unsigned short
          ^
  <built-in>:288:9: error: macro is not used [-Werror,-Wunused-macros]
  #define __UINT_FAST64_FMTX__ "llX"
          ^
  <built-in>:95:9: error: macro is not used [-Werror,-Wunused-macros]
  #define __CHAR32_TYPE__ unsigned int
          ^
  <built-in>:345:9: error: macro is not used [-Werror,-Wunused-macros]
  #define __SSE_MATH__ 1
          ^
  <built-in>:96:9: error: macro is not used [-Werror,-Wunused-macros]
  #define __UINTMAX_WIDTH__ 64
          ^
  <built-in>:347:9: error: macro is not used [-Werror,-Wunused-macros]
  #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
          ^
  <built-in>:97:9: error: macro is not used [-Werror,-Wunused-macros]
  #define __UINTPTR_TYPE__ long unsigned int
          ^
  <built-in>:98:9: error: macro is not used [-Werror,-Wunused-macros]
  #define __UINTPTR_FMTo__ "lo"
          ^
  <built-in>:99:9: error: macro is not used [-Werror,-Wunused-macros]
  #define __UINTPTR_FMTu__ "lu"
          ^
  <built-in>:346:9: error: macro is not used [-Werror,-Wunused-macros]
  #define __MMX__ 1
          ^
  <built-in>:344:9: error: macro is not used [-Werror,-Wunused-macros]
  #define __SSE__ 1
          ^
  <built-in>:83:9: error: macro is not used [-Werror,-Wunused-macros]
  #define __SIZE_FMTo__ "lo"
          ^
  <built-in>:348:9: error: macro is not used [-Werror,-Wunused-macros]
  #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
          ^
  fatal error: too many errors emitted, stopping now [-ferror-limit=]
  20 errors generated.
  thread 'main' panicked at 'execution failed', /Users/chris/.cargo/registry/src/github.com-1ecc6299db9ec823/ring-0.16.20/build.rs:656:9
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
warning: build failed, waiting for other jobs to finish...
error: build failed

Provide a crates-centric view of publishers

It would be interesting to see the crate list sorted by number of publishers, so that crates with an excessive number of them or crates with the bus factor of 1 could be identified.

Help shows commands misaligned

image

Using tabs for alignment is wrong, they should only be used for initial indentation, since you don't know where the users tab stops will be.

Long incremental build times due to JSON schema generation

The incremental build times got significantly longer after I added JSON schema generation.

But it's supposed to be stable and not change between releases, let alone incremental builds, so we really don't need to re-generate it on every build. Instead, we could generate it once, hardcode it, and then only generate it when running tests and ensuring that it's the same as the one we've recorded earlier.

Add progress indication to `update` subcommand

cargo supply-chain update currently shows no output, and just does its job silently. This is bad for a couple of reasons:

  1. There is no indication that a lot of data is going to be downloaded (~250Mb as of right now, and growing). This may be unexpected and undesirable for people using mobile internet connections.
  2. On slow connections it's not apparent if any progress is happening or the program just hung.

We need to provide some sort of progress indication, e.g. the amount of data downloaded so far. We cannot show a real progressbar because it would require knowing the size in advance, as well as introducing complex dependencies.

It would also be nice to show some sort of warning that a lot of data may be downloaded.

Output is not available in json

Hey - I think it'd be useful if there were a json output format selectable with --json on the command line for all options.

I'd like to base some automation on this tooling but it's hard to do without an output format that I can connect to other things.

I may have a stab at doing this myself if you're okay with that.

Too many crates are included in the analysis

For example, when run on itself the base-x crate is included in the analysis despite not showing up in cargo tree output. It is probably either a dev-dependency or a feature-gated dependency of something.

Could not load platform certs: "The Trust Settings Record was corrupted."

$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.14.6
BuildVersion:	18G8022
$ rustc --version
rustc 1.50.0 (cb75ad5db 2021-02-10)
$ cargo install cargo-supply-chain
[...]
   Installed package `cargo-supply-chain v0.1.1` (executable `cargo-supply-chain`)
$ cargo supply-chain update
Note: this will download large amounts of data (approximately 250Mb).
On a slow network this will take a while.
thread 'main' panicked at 'Could not load patform certs: (None, Custom { kind: Other, error: Error { code: -25262, message: "The Trust Settings Record was corrupted." } })', /Users/eden/.cargo/registry/src/github.com-1ecc6299db9ec823/ureq-2.0.2/src/stream.rs:320:50
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
$ RUST_BACKTRACE=1 cargo supply-chain update
Note: this will download large amounts of data (approximately 250Mb).
On a slow network this will take a while.
thread 'main' panicked at 'Could not load patform certs: (None, Custom { kind: Other, error: Error { code: -25262, message: "The Trust Settings Record was corrupted." } })', /Users/eden/.cargo/registry/src/github.com-1ecc6299db9ec823/ureq-2.0.2/src/stream.rs:320:50
stack backtrace:
   0: rust_begin_unwind
             at /rustc/152f6609246558be5e2582e67376194815e6ba0d/library/std/src/panicking.rs:493:5
   1: core::panicking::panic_fmt
             at /rustc/152f6609246558be5e2582e67376194815e6ba0d/library/core/src/panicking.rs:92:14
   2: core::option::expect_none_failed
             at /rustc/152f6609246558be5e2582e67376194815e6ba0d/library/core/src/option.rs:1300:5
   3: core::ops::function::FnOnce::call_once
   4: once_cell::imp::OnceCell<T>::initialize::{{closure}}
   5: once_cell::imp::initialize_inner
   6: once_cell::imp::OnceCell<T>::initialize
   7: ureq::stream::connect_https
   8: ureq::unit::connect_socket
   9: ureq::unit::connect_inner
  10: ureq::unit::connect
  11: ureq::request::Request::do_call
  12: ureq::request::Request::call
  13: cargo_supply_chain::crates_cache::CratesCache::download
  14: cargo_supply_chain::subcommands::update::update
  15: cargo_supply_chain::main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

publishers and crates commands report the same.

Authors are duplicated if the registry differs

$ cargo supply-chain authors
Alex Crichton <[email protected]>		local
Alex Crichton <[email protected]>		unknown registry
Guillaume Gomez <[email protected]>		local
Guillaume Gomez <[email protected]>		unknown registry
Manish Goregaokar <[email protected]>		local
Manish Goregaokar <[email protected]>		unknown registry

It might also be nice to deduplicate by the author name, but that's more risky since you don't actually know the same name is the same person. Deduplicating by email would be nice though:

Nicholas Cameron <[email protected]>		local
Nick Cameron <[email protected]>		local
Nick Cameron <[email protected]>		unknown registry

Allow excluding dev-dependencies

If you're looking at someone else's crate to see what it will bring in as part of its supply chain you don't necessarily care about its dev-dependency supply chain. It would be useful to have a flag like cargo supply-chain publishers --no-dev to exclude them from the list (and maybe mark normal/build/dev differently somehow in the standard output).

Removing help commands from README.md

I'm not sure if the help commands are needed in the README.md as they are worded differently and don't look great, an alternative to just deleting them could be copying and pasting the help message contained in cargo-supply-chain itself into the README.md as a codeblock.

Does not complain about invalid arguments

cargo-supply-chain crates --nosucharg does not complain that the argument --nosucharg does not exist. The underlying pico-args does that, but apparently some logic we had to put on top to handle -- broke it.

This worked correctly prior to the migration to pico-args in #27

Licenses

It might be useful to get an overview of all licenses used in dependencies.

This might be particularly interesting if new versions use a different license than older dependency versions used (e.g. like the MongoDB or Elasticsearch license changes).

Migrate to `anyhow` crate for error handling

Right now we have the err_exit function that just prints the error and exits:

// TODO: remove all uses of this and return error from the function instead
pub(crate) fn err_exit(msg: &str) -> ! {
match msg.into() {
Some(v) => eprintln!("{}", v),
None => (),
};
std::process::exit(1)
}

This makes code difficult to test, because it just exits the testing process on error. We should return errors instead.

The anyhow crate makes that rather easy, and is low on supply chain sprawl (unlike something like color-eyre).

Detailed help for each command

Right now the tool does not provide detailed information on behavior of each command. We have a bit more in the README, but it's still not that great.

cargo supply-chain help SUBCOMMAND and cargo supply-chain SUBCOMMAND --help should provide more detailed info on each command - that's what cargo build does.

Output should be consistently sorted

In order to try and check how adding a dependency affected the overall tree I stored the before/after output into files and diffed it, unfortunately this resulted in the entire file appearing as changed because the order of crates in each line changed:

> cargo supply-chain publishers > before
> cargo add indicatif
> cargo supply-chain publishers > after
> diff -u before after
- 1. "github:rustwasm:core" via crates: wasm-bindgen-macro-support, web-sys, js-sys, wasm-bindgen-shared, wasm-bindgen, wasm-bindgen-macro, wasm-bindgen-backend
+ 1. "github:rustwasm:core" via crates: js-sys, web-sys, wasm-bindgen, wasm-bindgen-backend, wasm-bindgen-shared, wasm-bindgen-macro-support, wasm-bindgen-macro

Run tests on CI

We currently only run cargo build, cargo doc and something like cargo fmt --verify on CI. We also need to run the unit tests now that we have them, via cargo test.

Add --offline capability

I want to run the tool without internet access (inside a nix build).
But right now it does not seem to be possible.

Could a feature for this be added?

Consider transparently downloading the DB dump instead of fetching live results by default

TL;DR: run cargo supply-chain update implicitly from other commands, instead of defaulting to querying the API.

If the cache is expired or nonexistent, and --cache-max-age allows it, we could download the latest DB dump by default instead of fetching live results. This would be a lot faster in the typical case.

We would still need to fall back to querying live data from the API if the latest DB dump published by crates.io is older than --cache-max-age.

Don't panic on network failure

Currently cargo supply-chain panics if an API call fails because of this .unwrap():

users.insert(
crate_name.clone(),
publisher_users(&mut client, crate_name).unwrap(), //TODO: don't panic
);
teams.insert(
crate_name.clone(),
publisher_teams(&mut client, crate_name).unwrap(), //TODO: don't panic
);

We should retry the request a few times instead of panicking.

Flag optional dependencies or publishers

It would be nice to provide actionable insights in publishers subcommand - i.e. whether you can remove a certain publisher by disabling certain features on crates the dependency tree; and if so, what features would that be.

I imagine the same could apply to crates in the crates subcommand.

Faster crates.io fetching?

Awesome project, been wanting a tool with this type of functionality for a while and really glad ran into it!

We have a fairly large project with, ahem, 548 crate dependencies, so the 2 second delay between fetching data on each crates.io well does add up quite a bit!

Fetching publisher info from crates.io
This will take roughly 2 seconds per crate due to API rate limits
Fetching data for "addr2line" (0/548)
Fetching data for "adler" (1/548)

Are there any paths to speeding this up?

  • Can one simply increase the rate limit / lower the delay?
  • Does crates.io support some type of batched queries?
  • Could one add support for crates.io API tokens and not be rate limited? Though those tokens seem to be read/write, where here one only wants read-only access to the database, some may be uncomfortable technically giving publishing access tokens laying around

Don't panic if the current directory is not a cargo project

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: CargoMetadata { stderr: "error: could not find `Cargo.toml` in `/home/joshua` or any parent directory\n" }', /home/joshua/.local/lib/cargo/registry/src/github.com-1ecc6299db9ec823/cargo-supply-chain-0.0.2/src/common.rs:28:10

Dependencies from other platforms are reported as "not from crates.io"

The output of cargo supply-chain on itself reports this:

Cannot audit the following crates because they are not from crates.io:
 - chunked_transfer
 - const_fn
 - discard
 - itoa
 - matches
 - percent-encoding
 - semver-parser
 - spin
 - stdweb-internal-runtime
 - unicode-xid
 - untrusted
 - version_check
 - wasm-bindgen-shared
 - winapi-i686-pc-windows-gnu
 - winapi-x86_64-pc-windows-gnu

I doubt they all come from git repos or some such. This is probably a bug.

See also #4

Migrate to ureq 2.0

We're currently using ureq 1.0, which necessitates rather ugly error handling. We should upgrade to ureq 2.0 which streamlined error handling.

Cache "live" results from crates.io

When downloading data via the crates.io API, we could cache it for later reuse. This would help if the user wants to view both crates and publishers commands for their crate or adjust the cargo-metadata parameters (e.g. target platform).

The timestamp of when the data was downloaded should be preserved; the cached data should be used only if the --cache-max-age configuration allows it.

If there are any cache entries with a timestamp from the future, they should be discarded.

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.