Giter Club home page Giter Club logo

sbtix's Introduction

sbtix's People

Contributors

nightkr 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

Watchers

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

sbtix's Issues

POM download fails with https CA error

Just installed sbtix and tried to run genNix on my project, the following happens:

> genNix
[info] Fetching file:/home/philipp/.coursier/cache/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.10.6/scala-library-2.10.6.jar
path is ‘/nix/store/g9b5h1skjbbby091jl3zgv9m0vp4wb5b-scala-library-2.10.6.jar’
[info] Fetching https://repo1.maven.org/maven2/org/scala-lang/scala-library/2.10.6/scala-library-2.10.6.pom
error: unable to download ‘https://repo1.maven.org/maven2/org/scala-lang/scala-library/2.10.6/scala-library-2.10.6.pom’: Problem with the SSL CA cert (path? access rights?) (77)
[trace] Stack trace suppressed: run last root/*:genNixRepo for the full output.
[error] (root/*:genNixRepo) Nonzero exit value: 1
scala.MatchError: Some((sbt.State@328446e1,Inc(Incomplete(node=Some(ScopedKey(Scope(Select(ProjectRef(file:/home/philipp/Projects/fhnw/viskar/VISKAR/src/server/,root)),Global,Global,Global),genNixRepo)), tpe=Error, msg=None, causes=List(), directCause=Some(java.lang.RuntimeException: Nonzero exit value: 1))))) (of class scala.Some)
    at se.nullable.sbtix.NixPlugin$$anonfun$genNixCommand$1$$anonfun$1.apply(NixPlugin.scala:31)
    at se.nullable.sbtix.NixPlugin$$anonfun$genNixCommand$1$$anonfun$1.apply(NixPlugin.scala:30)
    at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
    at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
    at scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:59)
    at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:47)
    at scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:251)
    at scala.collection.AbstractTraversable.flatMap(Traversable.scala:105)
    at se.nullable.sbtix.NixPlugin$$anonfun$genNixCommand$1.apply(NixPlugin.scala:30)
    at se.nullable.sbtix.NixPlugin$$anonfun$genNixCommand$1.apply(NixPlugin.scala:24)
    at sbt.Command$$anonfun$command$1$$anonfun$apply$1.apply(Command.scala:30)
    at sbt.Command$$anonfun$command$1$$anonfun$apply$1.apply(Command.scala:30)
    at sbt.Command$.process(Command.scala:93)
    at sbt.MainLoop$$anonfun$1$$anonfun$apply$1.apply(MainLoop.scala:96)
    at sbt.MainLoop$$anonfun$1$$anonfun$apply$1.apply(MainLoop.scala:96)
    at sbt.State$$anon$1.process(State.scala:184)
    at sbt.MainLoop$$anonfun$1.apply(MainLoop.scala:96)
    at sbt.MainLoop$$anonfun$1.apply(MainLoop.scala:96)
    at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:17)
    at sbt.MainLoop$.next(MainLoop.scala:96)
    at sbt.MainLoop$.run(MainLoop.scala:89)
    at sbt.MainLoop$$anonfun$runWithNewLog$1.apply(MainLoop.scala:68)
    at sbt.MainLoop$$anonfun$runWithNewLog$1.apply(MainLoop.scala:63)
    at sbt.Using.apply(Using.scala:24)
    at sbt.MainLoop$.runWithNewLog(MainLoop.scala:63)
    at sbt.MainLoop$.runAndClearLast(MainLoop.scala:46)
    at sbt.MainLoop$.runLoggedLoop(MainLoop.scala:30)
    at sbt.MainLoop$.runLogged(MainLoop.scala:22)
    at sbt.StandardMain$.runManaged(Main.scala:54)
    at sbt.xMain.run(Main.scala:29)
    at xsbt.boot.Launch$$anonfun$run$1.apply(Launch.scala:109)
    at xsbt.boot.Launch$.withContextLoader(Launch.scala:128)
    at xsbt.boot.Launch$.run(Launch.scala:109)
    at xsbt.boot.Launch$$anonfun$apply$1.apply(Launch.scala:35)
    at xsbt.boot.Launch$.launch(Launch.scala:117)
    at xsbt.boot.Launch$.apply(Launch.scala:18)
    at xsbt.boot.Boot$.runImpl(Boot.scala:41)
    at xsbt.boot.Boot$.main(Boot.scala:17)
    at xsbt.boot.Boot.main(Boot.scala)
[error] scala.MatchError: Some((sbt.State@328446e1,Inc(Incomplete(node=Some(ScopedKey(Scope(Select(ProjectRef(file:/home/philipp/Projects/fhnw/viskar/VISKAR/src/server/,root)),Global,Global,Global),genNixRepo)), tpe=Error, msg=None, causes=List(), directCause=Some(java.lang.RuntimeException: Nonzero exit value: 1))))) (of class scala.Some)
[error] Use 'last' for the full log.

I am on NixOS, using sbt 0.13.12. Any idea what the problem might be?

sbtix-gen-* crashes when nix-daemon is enabled

I'm trying to use sbtix on https://github.com/tumblr/collins (master, which is 5856ac90485baf140d248f668a4e68ad9290eaec at this time.)

I've applied the following patch:

diff --git a/build.sbt b/build.sbt
index 9cf9a226..98977913 100644
--- a/build.sbt
+++ b/build.sbt
@@ -4,6 +4,8 @@ resolvers += "Sonatype-public" at "http://oss.sonatype.org/content/groups/public
 
 resolvers += "Restlet repository" at "http://maven.restlet.org"
 
+resolvers += Resolver.url("sbt-plugins-releases", url("https://dl.bintray.com/playframework/sbt-plugin-releases"))(Resolver.ivyStylePatterns)
+
 Keys.fork in Test := true
 
 javaOptions in Test := Seq("-Dconfig.file=conf/test.conf", "-XX:MaxPermSize=512M", "-Xms512m", "-Xmx512m")
diff --git a/project/build.properties b/project/build.properties
index be6c454f..817bc38d 100644
--- a/project/build.properties
+++ b/project/build.properties
@@ -1 +1 @@
-sbt.version=0.13.5
+sbt.version=0.13.9
diff --git a/project/plugins.sbt b/project/plugins.sbt
index 974d35f0..638c541f 100644
--- a/project/plugins.sbt
+++ b/project/plugins.sbt
@@ -10,4 +10,3 @@ addSbtPlugin("com.typesafe.play" % "sbt-plugin" % Option(System.getProperty("pla
 addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "0.6.0")
 
 addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.3.3")
-

but I end up having sbtix-gen fail with the following output:

java.lang.RuntimeException: Nonzero exit value: 1
	at scala.sys.package$.error(package.scala:27)
	at scala.sys.process.ProcessBuilderImpl$AbstractBuilder.slurp(ProcessBuilderImpl.scala:131)
	at scala.sys.process.ProcessBuilderImpl$AbstractBuilder.$bang$bang(ProcessBuilderImpl.scala:102)
	at se.nullable.sbtix.FindArtifactsOfRepo$.fetchChecksum(FindArtifacts.scala:27)
	at se.nullable.sbtix.CoursierArtifactFetcher$$anonfun$CacheFetch_WithCollector$1$$anonfun$apply$3.apply(CoursierArtifactFetcher.scala:188)
	at se.nullable.sbtix.CoursierArtifactFetcher$$anonfun$CacheFetch_WithCollector$1$$anonfun$apply$3.apply(CoursierArtifactFetcher.scala:130)
	at scalaz.EitherT$$anonfun$flatMap$1$$anonfun$apply$4.apply(EitherT.scala:93)
	at scalaz.$bslash$div.fold(Either.scala:58)
	at scalaz.EitherT$$anonfun$flatMap$1.apply(EitherT.scala:93)
	at scalaz.EitherT$$anonfun$flatMap$1.apply(EitherT.scala:93)
	at scalaz.concurrent.Task$$anonfun$flatMap$1$$anonfun$1.apply(Task.scala:35)
	at scalaz.concurrent.Task$$anonfun$flatMap$1$$anonfun$1.apply(Task.scala:35)
	at scalaz.concurrent.Task$.Try(Task.scala:457)
	at scalaz.concurrent.Task$$anonfun$flatMap$1.apply(Task.scala:35)
	at scalaz.concurrent.Task$$anonfun$flatMap$1.apply(Task.scala:33)
	at scala.Function1$$anonfun$andThen$1.apply(Function1.scala:55)
	at scala.Function1$$anonfun$andThen$1.apply(Function1.scala:55)
	at scalaz.concurrent.Future$$anonfun$flatMap$1.apply(Future.scala:58)
	at scalaz.concurrent.Future$$anonfun$flatMap$1.apply(Future.scala:58)
	at scalaz.concurrent.Future.step(Future.scala:118)
	at scalaz.concurrent.Future.unsafePerformListen(Future.scala:75)
	at scalaz.concurrent.Future$$anonfun$unsafePerformListen$1$$anonfun$apply$4.apply(Future.scala:79)
	at scalaz.concurrent.Future$$anonfun$unsafePerformListen$1$$anonfun$apply$4.apply(Future.scala:79)
	at scalaz.Free$$anonfun$map$1.apply(Free.scala:91)
	at scalaz.Free$$anonfun$map$1.apply(Free.scala:91)
	at scalaz.Free.resume(Free.scala:109)
	at scalaz.Free.go2$1(Free.scala:153)
	at scalaz.Free.go(Free.scala:157)
	at scalaz.Free.run(Free.scala:263)
	at scalaz.concurrent.Future$$anonfun$apply$15$$anon$3.call(Future.scala:432)
	at scalaz.concurrent.Future$$anonfun$apply$15$$anon$3.call(Future.scala:432)
	at java.util.concurrent.FutureTask.run(FutureTask.java:262)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	at java.lang.Thread.run(Thread.java:745)
[error] Nonzero exit value: 1
[error] Use 'last' for the full log.

which I see is similar to issue #2, but I don't see a resolution for this. I'm running a205c0a and am using it by nix-build ./default.nix and then calling /Users/graham/projects/Sbtix/result/bin/sbtix-gen-all.

Plugins are not handled by Sbtix yet

Currently, plugins are still downloaded by SBT from the internet as usual. Ideally Sbtix should download these as well, and add them to the repo.

Sbtix should supply the SBT Compiler Interface dependency upfront

Even with plugin support Sbtix still misses dependencies. Those additional dependencies seem to come from the SBT Compiler Interface. Solving this will shave more than 3 seconds off every compile!

[info] 'compiler-interface' not yet compiled for Scala 2.10.6. Compiling...
[info]   Compilation completed in 3.469 s

A potential solution is to have the genNix command gather the sbt-scala version and the sbt version that will be used for the compiler interface in the Nix build of the user's project. Then Nix should be able to supply the correct compiler interface as a dependency to the project. To create a mvn repo containing the correct SBT Compiler Interface (maybe) use the SBT Republish project.

Relevant: SBT-DEV: how to build compiler-interface and incremental-compiler for scala 2.11

Feature requests to improve DX of this tool

Hey there,

I started playing around with this tool in the last time. I actually like the idea behind it, but there are some things I'd like to improve (please note that I'm opening an issue first to discuss, if @teozkr is fine with it, I'll open PRs for my requests)

  • copy manual-repo.nix into the directory during sbtix-gen-all2. I think its unnecessary to force users to copy the file from a cloned repo, this is definetely a step that can be automated
  • option to generate a default.nix with a sbtix.buildSbtProgram expression. This would make it easier to bootstrap/prototype applications in Scala as no extra packaging steps are needed and this sort of approach doesn't need much tweaking
  • copy/refresh all expressions in this repository. When driving such an approach sbtix itself ensures that everything is up-to-date. Right now it's up to the developer as he'd need to update the rev and sha256 in the fetchFromGitHub expression needed to download the internal SBTix API.

Thanks in advance :-)

POMs are not cached by genNix

Currently Coursier doesn't expose a neat way to access the raw Maven POMs. Currently this is worked around by replacing the file extension of the artifact with .pom, and then having nix-prefetch-url download it to find out the hash, but this has the suboptimal side effect of that we can't take advantage of Coursier's cache, and so each POM is downloaded first by Coursier, and then once per project that depends on it, per build.

As a workaround, it should be reasonable to use the same hack against the local file path, but I haven't got around to that (yet).

Document buildSbtLibrary

Currently the README doesn't mention how to import buildSbtLibrary-libraries, nor what it actually does.

The warning about source dependencies should probably also be replaced with a suggestion to use buildSbtLibrary instead, since that both fixes the original problem (ProjectRefs can refer to mutable Git branches, which breaks Nix purity) and allows Nix to cache libraries between builds.

SBT launcher throws exception in NixOs on nix-build

I am getting the following exception no matter what I do and I'm wondering if you are building this on NixOs or on another OS. It seems that the SBT launcher cannot create a file and its parent directories, probably because the file system is read-only or it simply doesn't have permissions. The error occurs in Locks.scala line 34.. But I do not yet know what file it is trying to create. The SBT launcher probably needs to be modified so it will report the filepath.

$ nix-build
these derivations will be built:
  /nix/store/44wm10qzhq7fb0pkip81zsy0xgy46d3p-sbtix-simple.drv
building path(s) ‘/nix/store/y6ab90bd4pqkal70irv4hcwcpiw756w0-sbtix-simple’
unpacking sources
unpacking source archive /nix/store/b3m0qvlbv4wbgyx75z7f3h3b2c1l8im8-simple
source root is simple
patching sources
configuring
building
java.io.IOException: No such file or directory
        at java.io.UnixFileSystem.createFileExclusively(Native Method)
        at java.io.File.createNewFile(File.java:1012)
        at xsbt.boot.Locks$.apply0(Locks.scala:34)
        at xsbt.boot.Locks$.apply(Locks.scala:28)
        at xsbt.boot.Launch.locked(Launch.scala:238)
        at xsbt.boot.Launch.app(Launch.scala:147)
        at xsbt.boot.Launch.app(Launch.scala:145)
        at xsbt.boot.Launch$.run(Launch.scala:102)
        at xsbt.boot.Launch$$anonfun$apply$1.apply(Launch.scala:35)
        at xsbt.boot.Launch$.launch(Launch.scala:117)
        at xsbt.boot.Launch$.apply(Launch.scala:18)
        at xsbt.boot.Boot$.runImpl(Boot.scala:41)
        at xsbt.boot.Boot$.main(Boot.scala:17)
        at xsbt.boot.Boot.main(Boot.scala)
Error during sbt execution: java.io.IOException: No such file or directory
builder for ‘/nix/store/44wm10qzhq7fb0pkip81zsy0xgy46d3p-sbtix-simple.drv’ failed with exit code 1
error: build of ‘/nix/store/44wm10qzhq7fb0pkip81zsy0xgy46d3p-sbtix-simple.drv’ failed

I think the sbt Launcher Configuration may need to be overridden. Alternatively we might be able to ditch the launcher altogether. And just run the underlying sbt app.

sbtix commands are unuseable within nix-shell

If nix-shell is used to load the sbtix build environment then sbtix commands are not useable.

Running nix-shell sets the SBT_OPTS environment variable, which interferes with the sbtix commands. Simply unsetting the SBT_OPTS environment fixes it. The sbtix script should ignore the SBT_OPTS settings without modifying the environment variable.

SBT_OPTS = ''
 -Dsbt.ivy.home=./.ivy2/
 -Dsbt.boot.directory=./.sbt/boot/
 -Dsbt.global.base=./.sbt
 -Dsbt.global.staging=./.staging
 -Dsbt.override.build.repos=true
 -Dsbt.repository.config=${sbtixRepos}
'';

one solution is to make this line in the sbtix script look like:

${sbt}/bin/sbt -Dsbt.global.base=$SBTIX_GLBASE_DIR -Dsbt.override.build.repos=false -Dsbt.repository.config -Dsbt.boot.directory -Dsbt.ivy.home -Dsbt.global.staging "$@"

Better way to build libraries

Currently, the documentation suggests building libraries by running sbt publishLocal and then copying .ivy2/local. However, there is no obvious way to then consume those dependencies, since we override all resolvers when building. Additionally, Nix-only dependencies break sbtix-gen-*, since it expects to be able to find all dependencies.

My current idea is to:

  • Add an argument called sbtixBuildInputs to buildSbtProject that takes a list of derivations (similar to how buildInputs works for $PATH and C libraries). Each derivation is assumed to build an Ivy-style repository, produced by sbt publish-local or similar, and is added to SBT's resolver list.
  • Add a wrapper called buildSbtLibrary around buildSbtProject that automatically builds a library suitable for inclusion into sbtixBuildInputs.
  • Add sbtixBuildInputs and repo to the derivation output by buildSbtProject.
  • Also consider sbtixBuildInputs and repo of entries of sbtixBuildInputs when building the project (and propagating dependencies).
  • Add some sort of marker for dependencies to not be considered by genNix. Perhaps just a separate list of Group/Artifact pairs?

Any thoughts on that approach?

Can't access private repository

Looks like the equivalent of coursierUseSbtCredentials isn't being set when fetching artifacts and I'm getting 401 Unauthorized when trying to get some private one.

Get rid of Nix dependency

As @Ma27 said in #26 (comment), not everyone can (Windows users) or wants to use Nix (yet, hopefully). Thus, being able to generate Nix builds without having it installed would help make it easier for upstreams to provide up-to-date build files.

  • Hash it ourselves instead of using nix-prefetch-scripts if it's not installed
  • Teach genNix about the "project" build, replacing sbtix-gen-all
  • Make sbt genNix the main entry point, rather than sbtix-gen
  • Drop the sbtix-gen* scripts
  • Publish to Maven Central! (eventually)

Have nix-build trigger regeneration of repo.nix files.

I think it may be possible to have the genNix commands triggered by nix-build and only as needed. If we get a hash representing our list of dependencies and write it to a file then we could check that hash and automatically run commands to regenerate repo.nix files as needed. Even better would be a way to diff the old dependencies and new ones and just update for the changes. Though we may want to switch to sbt 1.0 first.

`genNix` task hangs when run on the `Sbtix` project

I checked out revision d261602 (master at the time of this wring) of this project and ran:

$ cd Sbtix
$ nix-env --install --file .
...
building path(s) ‘/nix/store/y0p8pfv543a0skn9fa914yx1ayic2lba-sbtix-0.2’
installing
building path(s) ‘/nix/store/mgwkgkhzpk7a6gj299k8q6ygcrldisn3-user-environment’
created 80 symlinks in user environment
$ readlink $(type -p sbtix)
/nix/store/y0p8pfv543a0skn9fa914yx1ayic2lba-sbtix-0.2/bin/sbtix
$ cd plugin
$ sbtix
Deleting any cached sbtix plugins in '~/.ivy'. So the most recent version from nix is used.
Updating /Users/gabriel/.sbtix/plugins/sbtix_plugin.sbt symlink
[info] Loading global plugins from /Users/gabriel/.sbtix/plugins
[info] Updating {file:/Users/gabriel/.sbtix/plugins/}global-plugins...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Loading project definition from /Users/gabriel/proj/Sbtix/plugin/project
[info] Set current project to sbtix (in build file:/Users/gabriel/proj/Sbtix/plugin/)
> genNix

... and it hangs forever upon running the genNix task. I originally ran into this in the context of another Scala project, but was able to reproduce the same problem on the Sbtix project

Other information:

$ nix-env --version
nix-env (Nix) 1.11.16
$ uname -a
Darwin Gabriels-MacBook-Pro.local 17.5.0 Darwin Kernel Version 17.5.0: Mon Mar  5 22:24:32 PST 2018; root:xnu-4570.51.1~1/RELEASE_X86_64 x86_64

Unable to resolve sbtix plugin

I am trying out sbtix and getting the following problem.

$ sbtix-gen-all2
Deleting any cached sbtix plugins in '~/.ivy'. So the most recent version from nix is used.
Updating /home/eric/.sbtix/plugins/sbtix_plugin.sbt symlink
[info] Loading global plugins from /home/eric/.sbtix/plugins
[info] Updating {file:/home/eric/.sbtix/plugins/}global-plugins...
[info] Resolving se.nullable.sbtix#sbtix;0.2-SNAPSHOT ...
[warn]  module not found: se.nullable.sbtix#sbtix;0.2-SNAPSHOT
[warn] ==== typesafe-ivy-releases: tried
[warn]   https://repo.typesafe.com/typesafe/ivy-releases/se.nullable.sbtix/sbtix/scala_2.10/sbt_0.13/0.2-SNAPSHOT/ivys/ivy.xml
[warn] ==== sbt-plugin-releases: tried
[warn]   https://repo.scala-sbt.org/scalasbt/sbt-plugin-releases/se.nullable.sbtix/sbtix/scala_2.10/sbt_0.13/0.2-SNAPSHOT/ivys/ivy.xml
[warn] ==== local: tried
[warn]   /home/eric/.ivy2/local/se.nullable.sbtix/sbtix/scala_2.10/sbt_0.13/0.2-SNAPSHOT/ivys/ivy.xml
[warn] ==== jcenter: tried
[warn]   https://jcenter.bintray.com/se/nullable/sbtix/sbtix_2.10_0.13/0.2-SNAPSHOT/sbtix-0.2-SNAPSHOT.pom
[warn] ==== public: tried
[warn]   https://repo1.maven.org/maven2/se/nullable/sbtix/sbtix_2.10_0.13/0.2-SNAPSHOT/sbtix-0.2-SNAPSHOT.pom
[warn] ==== Sbtix Plugin Repo: tried
[warn]   /nix/store/gckifsabmvr67zgv4k8pnjcmqih1z9i6-sbtix-plugin/plugin-repo/se.nullable.sbtix/sbtix/scala_2.10/sbt_0.13/0.2-SNAPSHOT/ivys/ivy.xml
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[warn]  ::::::::::::::::::::::::::::::::::::::::::::::
[warn]  ::          UNRESOLVED DEPENDENCIES         ::
[warn]  ::::::::::::::::::::::::::::::::::::::::::::::
[warn]  :: se.nullable.sbtix#sbtix;0.2-SNAPSHOT: not found
[warn]  ::::::::::::::::::::::::::::::::::::::::::::::
[warn] 
[warn]  Note: Some unresolved dependencies have extra attributes.  Check that these dependencies exist with the requested attributes.
[warn]          se.nullable.sbtix:sbtix:0.2-SNAPSHOT (scalaVersion=2.10, sbtVersion=0.13)
[warn] 
[warn]  Note: Unresolved dependencies path:
[warn]          se.nullable.sbtix:sbtix:0.2-SNAPSHOT (scalaVersion=2.10, sbtVersion=0.13) (/home/eric/.sbtix/plugins/sbtix_plugin.sbt#L2-3)
[warn]            +- org.scala-sbt:global-plugins:0.0 (scalaVersion=2.10, sbtVersion=0.13)
sbt.ResolveException: unresolved dependency: se.nullable.sbtix#sbtix;0.2-SNAPSHOT: not found

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.