GithubHelp home page GithubHelp logo

pyflow's Introduction

crates.io version Build Status

Pyflow

Simple is better than complex - The Zen of Python

Pyflow streamlines working with Python projects and files. It's an easy-to-use CLI app with a minimalist API. Never worry about having the right version of Python or dependencies.

Example use, including setting up a project and switching Py versions: Demonstration

If your project's already configured, the only command you need is pyflow, or pyflow myscript.py; setting up Python and its dependencies are automatic.

Goals: Make using and publishing Python projects as simple as possible. Actively managing Python environments shouldn't be required to use dependencies safely. We're attempting to fix each stumbling block in the Python workflow, so that it's as elegant as the language itself.

You don't need Python or any other tools installed to use Pyflow.

It runs standalone scripts in their own environments with no config, and project functions directly from the CLI.

It implements PEP 582 -- Python local packages directory and Pep 518 (pyproject.toml).

Installation

  • Windows - Download and run this installer. Or, if you have Scoop installed, run scoop install pyflow.

  • Ubuntu, or another Os that uses Snap - Run snap install pyflow --classic.

  • Ubuntu or Debian without Snap - Download and run this deb.

  • Fedora, CentOs, RedHat, or older versions of SUSE - Download and run this rpm.

  • A different Linux distro - Download this standalone binary and place it somewhere accessible by the PATH. For example, /usr/bin.

  • Mac - Run brew install pyflow

  • With Pip - Run pip install pyflow. The linux install using this method is much larger than with the above ones, and it doesn't yet work with Mac. This method will likely not work with Red Hat, CentOs, or Fedora.

  • If you have Rust installed - Run cargo install pyflow.

Quickstart

  • (Optional) Run pyflow init in an existing project folder, or pyflow new projname to create a new project folder. init imports data from requirements.txt or Pipfile; new creates a folder with the basics.
  • Run pyflow install requests etc to install packages. Alternatively, edit pyproject.toml directly.
  • Run pyflow or pyflow myfile.py to run Python.

Quick-and-dirty start for quick-and-dirty scripts

  • Add the line __requires__ = ['numpy', 'requests'] somewhere in your script, where numpy and requests are dependencies.
  • Optionally add the line __python__ = X.Y.Z, where X.Y.Z is a Python version specification. Without this line, you will be prompted to choose a version when running the script.
  • Run pyflow script myscript.py, where myscript.py is the name of your script. This will set up an isolated environment for this script, and install dependencies as required. This is a safe way to run one-off Python files that aren't attached to a project, but have dependencies.

Why add another Python manager?

Pipenv, Poetry, and Pyenv address parts of Pyflow's raison d'être, but expose stumbling blocks that may frustrate new users, both when installing and using. Some reasons why this is different:

  • It behaves consistently regardless of how your system and Python installations are configured.

  • It automatically manages Python installations and environments. You specify a Python version in pyproject.toml (if omitted, it asks), and it ensures that version is used. If the version's not installed, Pyflow downloads a binary, and uses that. If multiple installations are found for that version, it asks which to use. Pyenv can be used to install Python, but only if your system is configured in a certain way: I don’t think expecting a user’s computer to compile Python is reasonable.

  • By not using Python to install or run, it remains environment-agnostic. This is important for making setup and use as simple and decision-free as possible. It's common for Python-based CLI tools to not run properly when installed from pip due to the PATH or user directories not being configured in the expected way.

  • Its dependency resolution and locking is faster due to using a cached database of dependencies, vice downloading and checking each package, or relying on the incomplete data available on the pypi warehouse. Pipenv’s resolution in particular may be prohibitively-slow on weak internet connections.

  • It keeps dependencies in the project directory, in __pypackages__. This is subtle, but reinforces the idea that there's no hidden state.

  • It will always use the specified version of Python. This is a notable limitation in Poetry; Poetry may pick the wrong installation (eg Python2 vice Python3), with no obvious way to change it. Poetry allows projects to specify version, but neither selects, nor provides a way to select the right one. If it chooses the wrong one, it will install the wrong environment, and produce a confusing error message. This can be worked around using Pyenv, but this solution isn't documented, and adds friction to the workflow. It may confuse new users, as it occurs by default on popular linux distros like Ubuntu. Additionally, Pyenv's docs are confusing: It's not obvious how to install it, what operating systems it's compatible with, or what additional dependencies are required.

  • Multiple versions of a dependency can be installed, allowing resolution of conflicting sub-dependencies. (ie: Your package requires Dep A>=1.0 and Dep B. Dep B requires Dep A==0.9) There are many cases where Poetry and Pipenv will fail to resolve dependencies. Try it for yourself with a few random dependencies from pypi; there's a good chance you'll hit this problem using Poetry or Pipenv. Limitations: This will not work for some compiled dependencies, and attempting to package something using this will trigger an error.

Perhaps the biggest philosophical difference is that Pyflow abstracts over environments, rather than expecting users to manage them.

My OS comes with Python, and Virtual environments are easy. What's the point of this?

Hopefully we're not replacing one problem with another.

Some people like the virtual-environment workflow - it requires only tools included with Python, and uses few console commands to create, and activate and environments. However, it may be tedious depending on workflow: The commands may be long depending on the path of virtual envs and projects, and it requires modifying the state of the terminal for each project, each time you use it, which you may find inconvenient or inelegant.

I think we can do better. This is especially relevant for new Python users who don't understand venvs, or are unaware of the hazards of working with a system Python.

Pipenv improves the workflow by automating environment use, and allowing reproducible dependency graphs. Poetry improves upon Pipenv's API, speed, and dependency resolution, as well as improving the packaging and distributing process by using a consolidating project config. Both are sensitive to the environment they run in, and won't work correctly if it's not as expected.

Conda addresses these problems elegantly, but maintains a separate repository of binaries from PyPi. If all packages you need are available on Conda, it may be the best solution. If not, it requires falling back to Pip, which means using two separate package managers.

When building and deploying packages, a set of overlapping files are traditionally used: setup.py, setup.cfg, requirements.txt and MANIFEST.in. We use pyproject.toml as the single-source of project info required to build and publish.

A thoroughly biased feature table

These tools have different scopes and purposes:

Name Pip + venv Pipenv Poetry pyenv pythonloc Conda this
Manages dependencies
Resolves/locks deps
Manages Python installations
Py-environment-agnostic
Included with Python
Stores deps with project
Requires changing session state
Clean build/publish flow
Supports old Python versions with virtualenv
Isolated envs for scripts
Runs project fns from CLI

Use

  • Optionally, create a pyproject.toml file in your project directory. Otherwise, this file will be created automatically. You may wish to use pyflow new to create a basic project folder (With a .gitignore, source directory etc), or pyflow init to populate info from requirements.txt or Pipfile. See PEP 518 for details.

Example contents:

[tool.pyflow]
py_version = "3.7"
name = "runcible"
version = "0.3.1"
authors = ["John Hackworth <[email protected]>"]

[tool.pyflow.dependencies]
numpy = "^1.16.4"
diffeqpy = "1.1.0"

The [tool.pyflow] section is used for metadata. The only required item in it is py_version, unless building and distributing a package. The [tool.pyflow.dependencies] section contains all dependencies, and is an analog to requirements.txt. You can specify developer dependencies in the [tool.pyflow.dev-dependencies] section. These won't be packed or published, but will be installed locally. You can install these from the cli using the --dev flag. Eg: pyflow install black --dev

You can specify extra dependencies, which will only be installed when passing explicit flags to pyflow install, or when included in another project with the appropriate flag enabled. Ie packages requiring this one can enable with pip install -e etc.

[tool.pyflow.extras]
test = ["pytest", "nose"]
secure = ["crypto"]

If you'd like to an install a dependency with extras, use syntax like this:

[tool.pyflow.dependencies]
ipython = { version = "^7.7.0", extras = ["qtconsole"] }

To install from a local path instead of pypi, use syntax like this:

[tool.pyflow.dependencies]
# packagename = { path = "path-to-package"}
numpy = { path = "../numpy" }

To install from a git repo, use syntax like this:

[tool.pyflow.dependencies]
saturn = { git = "https://github.com/david-oconnor/saturn.git" }  # The trailing `.git` here is optional.

gitdependencies are currently experimental. If you run into problems with them, please submit an issue.

To install a package that includes a . in its name, enclose the name in quotes.

For details on how to specify dependencies in this Cargo.toml-inspired semver format, reference this guide.

We also attempt to parse metadata and dependencies from tool.poetry sections of pyproject.toml, so there's no need to modify the format if you're using that.

You can specify direct entry points to parts of your program using something like this in pyproject.toml:

[tool.pyflow.scripts]
name = "module:function"

Where you replace name, function, and module with the name to call your script with, the function you wish to run, and the module it's in respectively. This is similar to specifying scripts in setup.py for built packages. The key difference is that functions specified here can be run at any time, without having to build the package. Run with pyflow name to do this.

If you run pyflow package on on a package using this, the result will work like normal script entry points for someone using the package, regardless of if they're using this tool.

What you can do

Managing dependencies:

  • pyflow install - Install all packages in pyproject.toml, and remove ones not (recursively) specified. If an environment isn't already set up for the version specified in pyproject.toml, sets one up. Note that this command isn't required to sync dependencies; any relevant pyflow command will do so automatically.
  • pyflow install requests - If you specify one or more packages after install, those packages will be added to pyproject.toml and installed. You can use the --dev flag to install dev dependencies. eg: pyflow install black --dev.
  • pyflow install numpy==1.16.4 matplotlib>=3.1 - Example with multiple dependencies, and specified versions
  • pyflow uninstall requests - Remove one or more dependencies

Running REPL and Python files in the environment:

  • pyflow - Run a Python REPL
  • pyflow main.py - Run a python file
  • pyflow ipython, pyflow black etc - Run a CLI tool like ipython, or a project function For the former, this must have been installed by a dependency; for the latter, it's specified under [tool.pyflow], scripts
  • pyflow script myscript.py - Run a one-off script, outside a project directory, with per-file package management

Building and publishing:

  • pyflow package - Package for distribution (uses setuptools internally, and builds both source and wheel.)
  • pyflow package --extras "test all" - Package for distribution with extra features enabled, as defined in pyproject.toml
  • pyflow publish - Upload to PyPi (Repo specified in pyproject.toml. Uses Twine internally.)

Misc:

  • pyflow list - Display all installed packages and console scripts
  • pyflow new projname - Create a directory containing the basics for a project: a readme, pyproject.toml, .gitignore, and directory for code
  • pyflow init - Create a pyproject.toml file in an existing project directory. Pull info from requirements.text and Pipfile as required.
  • pyflow reset - Remove the environment, and uninstall all packages
  • pyflow clear - Clear the cache, of downloaded dependencies, Python installations, or script- environments; it will ask you which ones you'd like to clear.
  • pyflow -V - Get the current version of this tool
  • pyflow help Get help, including a list of available commands

How installation and locking work

Running pyflow install syncs the project's installed dependencies with those specified in pyproject.toml. It generates pyflow.lock, which on subsequent runs, keeps dependencies each package a fixed version, as long as it continues to meet the constraints specified in pyproject.toml. Adding a package name via the CLI, eg pyflow install matplotlib simply adds that requirement before proceeding. pyflow.lock isn't meant to be edited directly.

Each dependency listed in pyproject.toml is checked for a compatible match in pyflow.lock If a constraint is met by something in the lock file, the version we'll sync will match that listed in the lock file. If not met, a new entry is added to the lock file, containing the highest version allowed by pyproject.toml. Once complete, packages are installed and removed in order to exactly meet those listed in the updated lock file.

This tool downloads and unpacks wheels from pypi, or builds wheels from source if none are available. It verifies the integrity of the downloaded file against that listed on pypi using SHA256, and the exact versions used are stored in a lock file.

When a dependency is removed from pyproject.toml, it, and its subdependencies not also required by other packages are removed from the __pypackages__ folder.

How dependencies are resolved

Compatible versions of dependencies are determined using info from the PyPi Warehouse (available versions, and hash info), and the pydeps database. We use pydeps, which is built specifically for this project, due to inconsistent dependency information stored on pypi. A dependency graph is built using this cached database. We attempt to use the newest compatible version of each package.

If all packages are either only specified once, or specified multiple times with the same newest-compatible version, we're done resolving, and ready to install and sync.

If a package is included more than once with different newest-compatible versions, but one of those newest-compatible is compatible with all requirements, we install that one. If not, we search all versions to find one that's compatible.

If still unable to find a version of a package that satisfies all requirements, we install multiple versions of it as-required, store them in separate directories, and modify their parents' imports as required.

Note that it may be possible to resolve dependencies in cases not listed above, instead of installing multiple versions. Ie we could try different combinations of top-level packages, check for resolutions, then vary children as-required down the hierarchy. We don't do this because it's slow, has no guarantee of success, and involves installing older versions of packages.

Not-yet-implemented

  • Installing global CLI tools
  • The lock file is missing some info like hashes
  • Adding a dependency via the CLI with a specific version constraint, or extras.
  • Install packages from a local wheel directly. In the meanwhile, you can use a path dependency of the unpacked wheel.
  • Dealing with multiple-installed-versions of a dependency that uses importlib or dynamic imports
  • Install Python on Mac

Building and uploading your project to PyPi

In order to build and publish your project, additional info is needed in pyproject.toml, that mimics what would be in setup.py. Example:

[tool.pyflow]
name = "everythingkiller"
py_version = "3.6"
version = "0.3.1"
authors = ["Fraa Erasmas <[email protected]>"]
description = "Small, but packs a punch!"
homepage = "https://everything.math"
repository = "https://github.com/raz/everythingkiller"
license = "MIT"
keywords = ["nanotech", "weapons"]
classifiers = [
    "Topic :: System :: Hardware",
    "Topic :: Scientific/Engineering :: Human Machine Interfaces",
]
python_requires = ">=3.6"
# If not included, will default to `test.pypi.org`
package_url = "https://upload.pypi.org/legacy/"


[tool.pyflow.scripts]
# name = "module:function"
activate = "jeejah:activate"


[tool.pyflow.dependencies]
numpy = "^1.16.4"
manimlib = "0.3.1"
ipython = {version = "^7.7.0", extras=["qtconsole"]}


[tool.pyflow.dev-dependencies]
black = "^18.0"

package_url is used to determine which package repository to upload to. If omitted, Pypi test is used (https://test.pypi.org/legacy/).

Other items you can specify in [tool.pyflow]:

  • readme: The readme filename, use this if it's named something other than README.md.
  • build: A python script to execute building non-python extensions when running pyflow package.

Building this from source

If you’d like to build from source, download and install Rust, clone the repo, and in the repo directory, run cargo build --release.

Ie on linux or Mac:

curl https://sh.rustup.rs -sSf | sh
git clone https://github.com/david-oconnor/pyflow.git
cd pyflow
cargo build --release

Updating

  • If installed via Scoop, run scoop update pyflow.
  • If installed via Snap, run snap refresh pyflow.
  • If installed via Cargo, run cargo install pyflow --force.
  • If installed via Pip, run pip install --upgrade pyflow.
  • If using an installer or deb, run the new version's installer or deb. If manually calling a binary, replace it.

Uninstalling

  • If installed via Scoop, run scoop uninstall pyflow.
  • If installed via Snap, run snap remove pyflow.
  • If installed via Cargo, run cargo uninstall pyflow.
  • If installed via Pip, run pip uninstall pyflow.
  • If installed via Windows installer, run the Installer again and select Remove when asked, or use Apps & features.
  • If installed via a deb, use the Software Center.
  • If manually calling a binary, remove it.

Contributing

If you notice unexpected behavior or missing features, please post an issue, or submit a PR. If you see unexpected behavior, it's probably a bug! Post an issue listing the dependencies that did not install correctly.

Why not to use this

  • It's adding another tool to an already complex field.
  • Most of the features here are already provided by a range of existing packages, like the ones in the table above.
  • The field of contributors is expected to be small, since it's written in a different language.
  • Dependency managers like Pipenv and Poetry work well enough for many cases, have dedicated dev teams, and large userbases.
  • Conda in particular handles many things this does quite well.

Dependency cache repo:

  • Github Example API calls: https://pydeps.herokuapp.com/requests, https://pydeps.herokuapp.com/requests/2.21.0. This pulls all top-level dependencies for the requests package, and the dependencies for version 2.21.0 respectively. There is also a POST API for pulling info on specified versions. The first time this command is run for a package/version combo, it may be slow. Subsequent calls, by anyone, should be fast. This is due to having to download and install each package on the server to properly determine dependencies, due to unreliable information on the pypi warehouse.

Python binary sources:

  • Windows: Python official Visual Studio package, by Steve Dower.
  • Newer linux distros: Built on Ubuntu 18.04, using standard procedures.
  • Older linux distros: Built on CentOS 7, using standard procedures.

Gotchas

  • Make sure __pypackages__ is in your .gitignore file.
  • You may need to set up IDEs to find packages in __pypackages__. If using PyCharm: SettingsProjectProject InterpreterShow All... → (Select the interpreter, ie (projname)/__pypackages__/3.x/.venv/bin/python on Linux/Mac, or (projname)/__pypackages__/3.x/Scripts/python on Windows) → Click the folder-tree icon at the bottom of the pop-out window → Click the + icon at the bottom of the new pop-out window → Navigate to and select (projname)/__pypackages__/3.x/lib
  • If using VsCode: Settings → search python extra pathsEdit in settings.json → Add or modify the line: "python.autoComplete.extraPaths": ["(projname)/__pypackages__/3.7/lib"]

References

pyflow's People

Contributors

515hikaru avatar altendky avatar atouchet avatar boxfort avatar branchvincent avatar cclauss avatar david-oconnor avatar dsully avatar elijahsink avatar higumachan avatar lau-jay avatar leos avatar markkoz avatar mataha avatar nimpruda avatar noeltautges avatar noritada avatar nuno-andre avatar rgreinho avatar shmokmt avatar simonrw avatar stranger6667 avatar tanj avatar ticecosmos avatar urotea avatar virviil avatar yawara 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pyflow's Issues

Question: Can I publish Pyflow on AUR?

First of all, thank you for your great work!
I really like its concept.

The Arch User Repositry (AUR) is a community-driven repository for Arch Linux users.
I'm using Manjaro Linux, the Arch based distro, so I made a AUR package for my own use.
Currently I'm using the package locally, but I interested to publish and maintain it.
If it's published, it'll be available through AUR helper like yay, tizen, etc.
Basically it's a kind of APT, Yum or Homebrew for Arch and Arch based distro users. (Technically it's a bit different though.)
Please let me know if it's ok with you.

Error parsing Os

[tool.pyflow.dependencies]
pywebview = { git = "https://github.com/r0x0r/pywebview" }

causes

❯ pyflow install
thread 'main' panicked at 'Problem parsing Os in extras: openbsd6', src\dep_types.rs:706:49

because of

install_requires = [
    ...,
    'PyQt5 ; sys_platform == "openbsd6"',
]

The point is that I'm running pyflow in Windows.

Given that sys.platform is built dynamically in most POSIX systems, as are other PEP508's environment markers, I think that a best-effort parsing of install_requires would be a more resilient approach.

Thank you for your work :) Python is greatly in need of tools like this.

The dependency cache is timing out

From #11

Installing a package which has an alias, like pyvbox/virtualbox, fails with:

Problem getting dependency data: DependencyError { details: "Network error" }

All features for a package must be union'd together

(From #32 (comment))

  1. pyflow new aaa ; cd aaa
  2. pyflow install ufoLib2 -- this will install fonttools[ufo]
  3. Add fonttools = {version = "^4.2.0", extras = ["ufo", "lxml", "unicode"]} to the pyproject.toml file.
  4. pyflow install

What happened: nothing. What I expected: the lxml and on Python < 3.8 unicodedata2 dependency are installed in addition to the [ufo] stuff.

Custom build process -- support / timeline?

Cool project!

Is it currently possible to make use of custom build systems for use with cython- and/or cmake-built extensions? If not, is this on the roadmap?

This is something I need in many of my projects that I've gotten working well with poetry via the use of a build.py file. I found a TODO reference to custom build systems; rather than digging more deeply into the source code (especially as someone with minimal familiarity with Rust) or playing around with the tool too much, I figured I might get a quicker answer by just asking.

Ability to target my own pypi repositories

Hello!

First issue posted there so tell me if I need to edit its description or title :)

So, I just want to be able to pull dependencies from my own artifactory or any other pypi clone I would own, from custom python builds installation to my own libraries.

I would love to contribute and help you do it if you're ok with it 👍

Thanks for reading.

Suggestion: Clippy

I tried running cargo clippy -- -W clippy::pedantic -W clippy::nursery -W clippy::cargo over pyflow, and I noticed that it suggested fixes for some of your todos (especially with filter_map). You may find it handy.

Scoop install proceeds on 32bit windows

Since pyflow.exe is 64bit only (AFAIK?) it should probably only have a architecture.64bit key in the scoop json manifest as per the scoop spec.

Or leave everything as is and just build a 32bit version going forward, I doubt there are any perf benefits that justify the slightly larger binary size?

For reference pyflow.exe v0.2.5.1 returns exit code 216 on windows 7 32bit.

Hard links for dependencies

Conda uses hard links between installed dependencies as a means of decreasing overall space. As best I could determine (without checking the code) I don't think pyflow does.

I have found this to be very useful in many scenarios:

  • Developing on laptops, where space is often at a premium.
  • Slow internet connections. (Conda avoids re-downloading.)
  • Quick spin-up of new environments. (Near instantaneous with conda, if the new environment uses packages which were already previously installed.)

I think it would be great if pyflow could implement something similar.

(And thanks again for writing this tool, which addresses an important need!)

Use the pip cache?

Reading the Readme, the point about pyflow using a cache stood out to me. Pip does it as well; on POSIX systems, look at ~/.cache/pip/wheels. Was there a reason it's not used for pyflow?

`pyflow script`: filename is mangled

  1. Be on git master
  2. Make a script a.py:
__requires__ = ["fonttools[ufo]"]

import fontTools.ufoLib
  1. pyflow script a.py
thread 'main' panicked at 'Problem opening the Python script file.: Os { code: 2, kind: NotFound, message: "No such file or directory" }', src/libcore/result.rs:1165:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

println!-debugging reveals filename in main.rs:970 to be "a_py". Looks like someone stepped on the dot.

Parse version from quick and dirty __requires__

I realise it goes against the 'quick-n-dirty' nature of this feature, but would be great if it supported pip style version spec like:

__requires__ = ['tornado<5', 'pywin32==227']
import tornado.httpserver
import win32api

In 0.2.5 I get the following error:

$ RUST_BACKTRACE=full pyflow script server.py
thread 'main' panicked at 'Problem getting version info for tornado<5', src\main.rs:1016:41
stack backtrace:
   0:     0x7ff6f30c5229 - <unknown>
   1:     0x7ff6f30e61bb - <unknown>
   2:     0x7ff6f30bd7f4 - <unknown>
   3:     0x7ff6f30c7d09 - <unknown>
   4:     0x7ff6f30c795c - <unknown>
   5:     0x7ff6f30c853c - <unknown>
   6:     0x7ff6f30c80c0 - <unknown>
   7:     0x7ff6f30c8004 - <unknown>
   8:     0x7ff6f2d38a23 - <unknown>
   9:     0x7ff6f2cfb89e - <unknown>
  10:     0x7ff6f2d0c0b6 - <unknown>
  11:     0x7ff6f30c7f17 - <unknown>
  12:     0x7ff6f30d5b42 - <unknown>
  13:     0x7ff6f30c8762 - <unknown>
  14:     0x7ff6f2d0b6f7 - <unknown>
  15:     0x7ff6f3106ce4 - <unknown>
  16:     0x7ff86be77bd4 - BaseThreadInitThunk
  17:     0x7ff86c0eced1 - RtlUserThreadStart

[UI] Unneccesary question about multiple system Python

I’m using Fedora and after creating a new project, I was asked the following:

$ pyflow install aiohttp
Found multiple compatible Python versions. Please enter the number associated with the
  one you’d like to use:
1: python3.7: 3.7.5
2: python3: 3.7.5
3: python: 3.7.5

Pyflow could detect it’s linking to the same version. Maybe it could even see if it’s about symlink to the same binary.
And then not ask this question.

Fails to run on mac

I installed with cargo from the master branch. When I run pyflow install numpy after entering a directory created with pyflow new projectname, I get (with RUST_BACTRACE=full):

🐍Setting up Python environment...
thread 'main' panicked at 'Problem creating lib directory: Os { code: 2, kind: NotFound, message: "No such file or directory" }', src/libcore/result.rs:1165:5
stack backtrace:
   0:        0x10d0ff995 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h458d13cb63d0c050
   1:        0x10d1259e0 - core::fmt::write::h53670af22ec3875f
   2:        0x10d0fa08b - std::io::Write::write_fmt::haf3d8737b9e851a5
   3:        0x10d101c8a - std::panicking::default_hook::{{closure}}::h3fbc052481cb023f
   4:        0x10d101995 - std::panicking::default_hook::h47b52fdc388b3b91
   5:        0x10d102357 - std::panicking::rust_panic_with_hook::he9c773346a268707
   6:        0x10d101ecd - std::panicking::continue_panic_fmt::h6ce88923515447fe
   7:        0x10d101e29 - rust_begin_unwind
   8:        0x10d13b59f - core::panicking::panic_fmt::h374d7a5fcdeaf2cf
   9:        0x10d13b679 - core::result::unwrap_failed::hdf38bf4ba53b175b
  10:        0x10cd74fb4 - pyflow::install::download_and_install_package::h962f28ab57bd4aee
  11:        0x10cd69612 - pyflow::py_versions::create_venv::hcb44ecfaa27a005d
  12:        0x10cd05525 - pyflow::util::find_venv_info::hb763c03c66689fc0
  13:        0x10cd45d58 - pyflow::main::hdf0794e46e104969
  14:        0x10cd29536 - std::rt::lang_start::{{closure}}::h26547f149e205262
  15:        0x10d101da8 - std::panicking::try::do_call::h1875c1f8f5700dda
  16:        0x10d10aaef - __rust_maybe_catch_panic
  17:        0x10d1027be - std::rt::lang_start_internal::h5206fcf99580d1b5
  18:        0x10cd4c699 - main

Use of Uvicorn

I've started a new package, installed uvicorn and fastapi and put the following in main.py:

from fastapi import FastAPI

app = FastAPI()


@app.get("/")
def read_root():
    return {"Hello": "World"}


@app.get("/items/{item_id}")
def read_item(item_id: int, q: str = None):
    return {"item_id": item_id, "q": q}

Trying to run this with pyflow python uvicorn package:main,pyflow uvicorn package:main doesn't work, can you clarify the syntax for running servers like gunicorn, uvicorn or hypercorn?

https://github.com/tiangolo/fastapi#example
Thanks

venv paths incorrect on windows

image

Standard Windows venv seems to be set up in .venv, but then packages seem to be installed in lib/, as if it detects a non-windows environment.

Could pyflow adopt Linux style venv paths on windows i.e. bin/ instead of Scripts/, lib instead of Lib etc. Not sure what the history for this difference is on windows.

`pyflow switch` does nothing

  1. git clone https://github.com/daltonmaag/statmake
  2. pyflow install
  3. pyflow -- should display some 3.6.x version
  4. pyflow switch 3.8 -- or something else you have lying around
  5. pyflow -- still displays 3.6.x :(

Configuring PyCharm for use with __pypackages__

I noticed this comment at the bottom of the docs:

You may need to set up IDEs to find packages in __pypackages__. If using PyCharm, using the tree on the left, right click __pypackages__/3.x/lib, select Mark directory as, Sources Root.

I haven't used the tool yet, but I'm assuming that __pypackages__ plays a similar role to the site-packages directory in a typical virtual environment.

If that's the case, rather than marking the directory as a sources root, I think you'd want to mark it as one of the "Interpreter Paths". Otherwise you'll get atypical search result behavior -- searching in your "Project" will also turn up results in the dependency packages.

(You could still search in the __pypackages__ folder under this approach by selecting it in the "Project" tab before triggering the "Find in Path" action, but if you mark it as a Sources Root I don't think there is an easy way to only search in your actual project.)


To mark a folder as one of the "Interpreter Paths" in PyCharm, you do:

Settings -> Project -> Project Interpreter -> (Settings Cog) -> Show All... -> Select the interpreter -> Click the folder-tree icon at the bottom of the pop-out window -> Click the + icon at the bottom of the new pop-out window -> Navigate to and select the folder you want to add (i.e., __pypackages__)

Admittedly this is relatively painful, but I think it would give a more typical PyCharm experience with a project structured like this.

(I haven't done it though so I could be wrong! Just figured it might be worth updating the docs if this is right and/or you've noticed any issues with the "Mark as Sources Root" approach.)

scoop install fails for v0.2.5

scoop install pyflow
WARN  Scoop uses 'aria2c' for multi-connection downloads.
WARN  Should it cause issues, run 'scoop config aria2-enabled false' to disable it.
Installing 'pyflow' (0.2.5) [64bit]
Loading pyflow.zip from cache.
Checking hash of pyflow.zip ... ok.
Extracting pyflow.zip ... done.
Linking ~\scoop\apps\pyflow\current => ~\scoop\apps\pyflow\0.2.5
Creating shim for 'pyflow'.
Can't shim 'pyflow.exe': File doesn't exist.

Pinning to v0.2.4 works for now:

scoop install [email protected]
WARN  Given version (0.2.4) does not match manifest (0.2.5)
WARN  Attempting to generate manifest for 'pyflow' (0.2.4)
Autoupdating pyflow
Downloading pyflow.zip to compute hashes!
Loading pyflow.zip from cache
Computed hash: 8724de8e6cbb5e4b3eb9653640b920ae08b595c1aebd1eda9df77db49ec4f308
Writing updated pyflow manifest
WARN  Scoop uses 'aria2c' for multi-connection downloads.
WARN  Should it cause issues, run 'scoop config aria2-enabled false' to disable it.
Installing 'pyflow' (0.2.4) [64bit]
Loading pyflow.zip from cache.
Checking hash of pyflow.zip ... ok.
Extracting pyflow.zip ... done.
Linking ~\scoop\apps\pyflow\current => ~\scoop\apps\pyflow\0.2.4
Creating shim for 'pyflow'.
'pyflow' (0.2.4) was installed successfully!

Support for __main__.py

I plan to adopt pyflow early in a production environment despite how young it is simply because it's that good. However I can't seem to be able to even run my project. Here's my (simplified) project structure:

__pypackages__
    [...]
myproject
    __main__.py
pyproject.toml

Here's what I've tried so far:

  • pyflow -m myproject

error: Found argument '-m' which wasn't expected, or isn't valid in this context

  • pyflow myproject

Problem running the CLI tool myproject. Is it installed?

  • pyflow python -m myproject

error: Found argument '-m' which wasn't expected, or isn't valid in this context

  • __pypackages__\3.7\.venv\Scripts\activate.bat followed by python -m myproject

ModuleNotFoundError: No module named 'click'

(main.py tries to import click but it fails.)

I'm out of ideas. Any help is appreciated!

Edit: I've now moved __main__.py out of myproject and renamed it to run.py, and I run it with pyflow run.py. It would be better if pyflow supported the standardized __main__.py in some way, though.

'Timed out waiting for venv to be created.'

With a fresh project, specifying only py_version = "3.7"

> env RUST_BACKTRACE=full pyflow
Please enter the number corresponding to your Linux distro:
1: 2016 or newer (Ubuntu≥16.04, Debian≥9, SUSE≥15, Arch, Kali, etc)
2: Older (Centos, Redhat, Fedora, older versions of distros listed in option 1)
1
Installing Python 3.7.4...
🐍 Setting up Python...
thread 'main' panicked at 'Timed out waiting for venv to be created.: AliasError { details: "Timed out attempting to create a directory" }', src/libcore/result.rs:1165:5
stack backtrace:
   0:     0x55c09138bba4 - <unknown>
   1:     0x55c0913b442c - core::fmt::write::h01edf6dd68a42c9c
   2:     0x55c0913860c7 - <unknown>
   3:     0x55c09138e745 - <unknown>
   4:     0x55c09138e436 - <unknown>
   5:     0x55c09138ee45 - std::panicking::rust_panic_with_hook::h825f041245da8739
   6:     0x55c09138e9e2 - <unknown>
   7:     0x55c09138e8d6 - rust_begin_unwind
   8:     0x55c0913b0e9a - core::panicking::panic_fmt::h527855ce0bc891f6
   9:     0x55c0913b0f97 - core::result::unwrap_failed::ha8b77e6004f0ba38
  10:     0x55c091012dc5 - <unknown>
  11:     0x55c090fd8b7b - <unknown>
  12:     0x55c090ffa202 - <unknown>
  13:     0x55c09102ed53 - <unknown>
  14:     0x55c09138e873 - <unknown>
  15:     0x55c091398c3a - __rust_maybe_catch_panic
  16:     0x55c09138f33d - std::rt::lang_start_internal::h409d4f2fe51133b0
  17:     0x55c0910029c2 - <unknown>
  18:     0x7f3402dc12e1 - __libc_start_main
  19:     0x55c090f27dc9 - <unknown>
  20:                0x0 - <unknown>

> tree __pypackages__/
__pypackages__/
└── 3.7
    └── lib

2 directories, 0 files

Environment:

  • Debian 9.7
  • pyflow 0.2.3 binary download from releases

Flasgger cannot be installed

$ pyflow install flasgger
Found lockfile
Resolving dependencies...
Can't find a compatible package for Req { name: "jsonschema", constraints: [Constraint { type_: Lt, version: 3.0.0 }], extra: None, sys_platform: None, python_version: None, install_with_extras: None, path: None, git: None }

Unable to create new project using pyflow

I am trying out pyflow, and when I am creating a new project using command pyflow new cool_project I am getting following error.

pyflow: error while loading shared libraries: libssl.so.1.0.0: cannot open shared object file: No such file or directory

I downloaded the binary and put that in the PATH, I am runnung Fedora 30 with python 3,7.4 and rust lang 1.38.

VSCode .venv detection

I'm not sure if this is strictly your problem per se, and I'm unsure if it'd get fixed by waiting and allowing the PEP-582 solution going into python 3.8 and thus hoping VSCode picks it up for detection, but it may be worth posting akin to the poetry project:

microsoft/vscode-python#1871

I don't know the details of the PEP enough to know if your implementation is "standards compliant" enough that this will eventually filter down anyway.

Food for thought - I expect they'll want a larger userbase and a more mature project before supporting it specially though.

As an aside I'm left in a bit of a pickle now as to what to set the python interpreter too on VSCode to do linting/formatting.

Permission problems in WSL

pyflow verison: 0.1.5
OS: WSL (windows subsystem for linux ver. 1)
I started a new project with pyflow new, then tried to add dependencies and getting (run with backtrace=full):

RUST_BACKTRACE=full pyflow install starlette                                                                                                Found lockfile
🔍 Resolving dependencies...
⬇ Installing starlette 0.12.9 ...
thread 'main' panicked at 'Problem reading the dist directory of a package built from source. The `wheel` package have not have been installed in this environment.: Os { code: 2, kind: NotFound, message: "No such file or directory" }', src/libcore/result.rs:1084:5
stack backtrace:
   0:     0x7f782526cceb - <unknown>
   1:     0x7f782526c9c6 - <unknown>
   2:     0x7f782526d45d - std::panicking::rust_panic_with_hook::h92f98b46e22f14ed
   3:     0x7f782526cfe2 - <unknown>
   4:     0x7f782526cec6 - rust_begin_unwind
   5:     0x7f782528ef9d - core::panicking::panic_fmt::h7e9f94035af782b3
   6:     0x7f782528f097 - core::result::unwrap_failed::hf7591c1dd9412006
   7:     0x7f7824f719d4 - <unknown>
   8:     0x7f7824f57652 - <unknown>
   9:     0x7f7824f5fcb0 - <unknown>
  10:     0x7f7824ec7f23 - <unknown>
  11:     0x7f782526ce63 - <unknown>
  12:     0x7f7825276b8a - __rust_maybe_catch_panic
  13:     0x7f782526da2d - std::rt::lang_start_internal::hea1b49a567afe309
  14:     0x7f7824f644b2 - <unknown>
  15:     0x7f7823701b97 - __libc_start_main
  16:     0x7f7824e8c289 - <unknown>
  17:                0x0 - <unknown>

I managed to install yapf, but many others fail. For example installing pytest breaks when wcwidth is installed for example.

Suggestion: Publish prebuilt wheels on PyPI

It would be great if users can install pyflow with pip. It can be done by publishing a prebuilt binary wheel on PyPI for every OS arch. I am not familiar with this task but setuptools-rust may be helpful.

Weird name for init

pyflow init seems to pick up the wrong name field from git config. My gitconfig:

[user]
	name = a
[merge "jupyternotebook"]
	driver = git-nbmergedriver merge %O %A %B %L %P
	name = jupyter notebook merge driver

It uses the name field under the merge table, which is clearly wrong.

Suggestion: Generates LICENSE with content or not create LICENSE

Hello.

Now, pyflow init generates LICENSE, which I don't think is useful.
This is because I create license file on github.com, and empty LICENSE makes it unavailable.
I have two alternative ideas as follows.

  1. pyflow init does not create LICENSE
  2. pyflow init make user choose using license (including nothing), and generates it as users choose.

As you know, cargo new does not create LICENSE, for the first idea is sufficient, I think.
Please think on it.

Regards.

Quick-and-dirty fails to install pywin32

server.py:

__requires__ = ['pywin32']
import win32api

Result:

$ RUST_BACKTRACE=full pyflow script server.py
Please enter the Python version for this project: (eg: 3.8)
3.8
Found multiple compatible Python versions. Please enter the number associated with the one you'd like to use:
1: python3: 3.8.2
2: python: 3.8.2
1
Setting up Python...
Installing pywin32 227.0.0 ...
Traceback (most recent call last):
  File "server.py", line 3, in <module>
    import win32api
ModuleNotFoundError: No module named 'win32api'

This is for latest version, v0.2.5

P.s. Where is the venv created when using this feature?

P.s.2. Are the __requires__ elements supposed to be quoted? They aren't in the docs, looks strange and will gen syntax errors in IDEs

Cannot install packages

Pyflow 0.1.9, Fedora 31, Python 3.7.5.

/tmp $ pyflow new ppp
Created a new Python project named ppp

/tmp $ cd ppp

/t/ppp (master|…) $ nvim pyproject.toml

/t/ppp (master|…) $ cat pyproject.toml 
# See PEP 518: https://www.python.org/dev/peps/pep-0518/ for info on this file's structure.

[tool.pyflow]
name = ""
py_version = "3.7"
version = "0.1.0"
authors = ["..."]

[tool.pyflow.scripts]

[tool.pyflow.dependencies]

[tool.pyflow.dev-dependencies]
pytest = "*"

/t/ppp (master|…) $ pyflow install
Found multiple compatible Python versions. Please enter the number associated with the one you'd like to use:
1: python3.7: 3.7.5
2: python3: 3.7.5
3: python: 3.7.5
3
🐍 Setting up Python...
🔍 Resolving dependencies...
Problem getting dependency data - this is likely a bug in the cacheing process. Please try again in a few minutes. Reqs: [
    Req {
        name: "six",
        constraints: [],
        extra: None,
        sys_platform: None,
        python_version: None,
        install_with_extras: None,
        path: None,
        git: None,
    },
    Req {
        name: "pyparsing",
        constraints: [
            Constraint {
                type_: Gte,
                version: 2.0.2,
            },
        ],
        extra: None,
        sys_platform: None,
        python_version: None,
        install_with_extras: None,
        path: None,
        git: None,
    },
]

`pyflow init` fails

Hello.
I want to initialize pyflow project from existing Pipfile, however pyflow init fails even in empty directory. How can I do?

$ mkdir test
$ cd test
$ pyflow init
To get started, run `pyflow new projname` to create a project folder, or `pyflow init` to start a project in this folder. For a list of what you can do, run `pyflow help`.

My environment is as follows.

  • Ubuntu 18.04
  • cargo: 1.39.0
  • pyflow: 0.2.3 (installed by cargo)

Regards.

Adherence to XDG User Directories or Systemd file-heirarchy spec

Hey, thanks for making this tool - trying it out now.

Noticed installation of python binaries goes into ~/python-installs, I'm on a bit of a crusade to clean up my home directory so I know what's worth backing up and not.

Would it be possible to put them in a ~/.local subdirectory?
In this example I think the path would be ~/.local/bin/python-installs/

Got this by running systemd-path user-binaries.

Just wanted to open up a discussion on where installed resources land in a user directory! Feel free to mark this closed if ~/python-installs is by design or by preference.

Thanks again!

More here:
https://www.freedesktop.org/software/systemd/man/file-hierarchy.html#Home%20Directory

Installing future fails

Thanks for creating this! I ran into an issue, however, upon initial usage when using pyflow to install pytorch:

~> pyflow new test_pyflow_1
Please enter the Python version for this project: (eg: 3.8)
3.7
Created a new Python project named test_pyflow_1
 > cd test_pyflow_1/
 ~/test_pyflow_1 > ../pyflow install torch
🐍 Setting up Python...
⬇ Installing future 0.18.2 ...
thread 'main' panicked at 'Problem running setup.py bdist_wheel: Os { code: 2, kind: NotFound, message: "No such file or directory" }', src/libcore/result.rs:1188:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

I am running on Arch Linux with kernel 5.6.7. I tried using the downloadable binary, installing via cargo, and using the package in the AUR, all with the same result.

Mac binary

There are currently no Mac binaries or installers available. There should be no reason this doesn't work on Mac, but it's untested, and requires building from source, or installing via Cargo for now.

Support for Self-Signed Certificate Authorities

I am currently behind a firewall and need to support Self-Signed trusted Certificates. I have found no documentation on how to configure pyflow to use the ca-bundle. Below is the error i get when i try to use it.

PS C:\Users\w-user\project> pyflow install
Downloading Python 3.8.0...
thread 'main' panicked at 'Problem downloading Python: Error(Hyper(Error(Connect, Custom { kind: Other, error: Custom { kind: InvalidData, error: WebPKIError(UnknownIssuer) } })), "https://github.com/David-OConnor/pybin/releases/download/3.8.0/python-3.8.0-windows.tar.xz")', src\libcore\result.rs:1188:5
stack backtrace:
   0:     0x7ff722165229 - <unknown>
   1:     0x7ff7221861bb - <unknown>
   2:     0x7ff72215d7f4 - <unknown>
   3:     0x7ff722167d09 - <unknown>
   4:     0x7ff72216795c - <unknown>
   5:     0x7ff72216853c - <unknown>
   6:     0x7ff7221680c0 - <unknown>
   7:     0x7ff722182bdd - <unknown>
   8:     0x7ff722182cdf - <unknown>
   9:     0x7ff721ddc2b3 - <unknown>
  10:     0x7ff721d5ff59 - <unknown>
  11:     0x7ff721d9a3b0 - <unknown>
  12:     0x7ff721dac0b6 - <unknown>
  13:     0x7ff722167f17 - <unknown>
  14:     0x7ff722175b42 - <unknown>
  15:     0x7ff722168762 - <unknown>
  16:     0x7ff721dab6f7 - <unknown>
  17:     0x7ff7221a6ce4 - <unknown>
  18:     0x7ffd36fb7974 - BaseThreadInitThunk
  19:     0x7ffd3998a271 - RtlUserThreadStart

Is this feature not supported? If so can you add support for it? Ideally I would like to give the path of ca-bundle in pyproject.toml and it needs to be used for any requests you make.
Eg: Installation of python or Install from pip or install from github.

tools like `black` don't work with VSCode

I installed black(pflow install --dev black) and set "python.autoComplete.extraPaths": ["__pypackages__/3.7/lib"] , but VSCode formatter did not work.

Setting black path to __pypackages__/3.7/bin/black or __pypackages__/3.7/lib/black has no effects. Are there any workarounds?

Note that pflow black works as expected.

Add debug/verbose logging

Maybe match python/pip syntax; -v is verbose, -vv is more verbose and so on.

FYI I'm adding this issue first as on first use I get an error when trying to install any package:

$ pyflow install black
Resolving dependencies...
Problem getting dependency data: DependencyError { details: "Network error" }

Not adding an issue for this error in case its something simple I'm missing, that logging would help identify.

FYI I'm using git for windows shell (MSYS2), installing by dropping binary in /usr/local/bin/

Typo in help.

diff --git a/src/main.rs b/src/main.rs
index 20c4eea..8e90630 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -144,7 +144,7 @@ Install packages from `pyproject.toml`, `pyflow.lock`, or speficied ones. Exampl
         #[structopt(name = "args")]
         args: Vec<String>,
     },
-    /// Change Python versions for this project. eg `pyflow swtich 3.7`. Equivalent to setting
+    /// Change Python versions for this project. eg `pyflow switch 3.7`. Equivalent to setting
     /// `py_version` in `pyproject.toml`.
     #[structopt(name = "switch")]
     Switch {

Dependency to source only package cause error

When dependency is a source only distribution, I got error. Here is a procedure to reproduce it.
pyflow 0.2.3
OS: Linux Mint 19.2

~/tmp$ pyflow new proj
Please enter the Python version for this project: (eg: 3.8)
3.8
Created a new Python project named proj
~/tmp$ cd proj
~/tmp/proj (master #)$ RUST_BACKTRACE=full pyflow install ifaddr
⬇ Installing ifaddr 0.1.6 ...
thread 'main' panicked at 'Problem running setup.py bdist_wheel: Os { code: 2, kind: NotFound, message: "No such file or directory" }', src/libcore/result.rs:1165:5
stack backtrace:
   0:     0x55d79b1daba4 - <unknown>
   1:     0x55d79b20342c - core::fmt::write::h01edf6dd68a42c9c
   2:     0x55d79b1d50c7 - <unknown>
   3:     0x55d79b1dd745 - <unknown>
   4:     0x55d79b1dd436 - <unknown>
   5:     0x55d79b1dde45 - std::panicking::rust_panic_with_hook::h825f041245da8739
   6:     0x55d79b1dd9e2 - <unknown>
   7:     0x55d79b1dd8d6 - rust_begin_unwind
   8:     0x55d79b1ffe9a - core::panicking::panic_fmt::h527855ce0bc891f6
   9:     0x55d79b1fff97 - core::result::unwrap_failed::ha8b77e6004f0ba38
  10:     0x55d79ae69812 - <unknown>
  11:     0x55d79ae422f1 - <unknown>
  12:     0x55d79ae4d248 - <unknown>
  13:     0x55d79ae7dd53 - <unknown>
  14:     0x55d79b1dd873 - <unknown>
  15:     0x55d79b1e7c3a - __rust_maybe_catch_panic
  16:     0x55d79b1de33d - std::rt::lang_start_internal::h409d4f2fe51133b0
  17:     0x55d79ae519c2 - <unknown>
  18:     0x7f5767267b97 - __libc_start_main
  19:     0x55d79ad76dc9 - <unknown>
  20:                0x0 - <unknown>
~/tmp/proj (master #)$ 

failed to install termcolor

pyflow install termcolor failed and so far I tracked that setup.py has no bdist_wheel target, changing target to bdist moves the error a little bit forward but later it stops trying to unzip the dist file.

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.