Giter Club home page Giter Club logo

wilderness's Introduction

Wilderness

PyPI version Build status Downloads Documentation Status

In wildness is the salvation of the world. โ€” Aldo Leopold

Wilderness is a light wrapper around argparse for creating command line applications with multiple subcommands, in the style of Git. Wilderness also makes it easy to generate man pages for your application.

Wilderness is heavily inspired by Cleo and argparse-manpage, but aims to stick as closely as possible to argparse to avoid users having to learn a new API.

Installation

Wilderness is available on PyPI:

$ pip install wilderness

Usage

Building command line applications with Wilderness is straightforward, but it does expect a certain structure of the application. You can create applications with or without subcommands, as illustrated with the fakegit and fakedf examples, respectively.

Creating wilderness applications consist of the following steps:

  1. Subclassing the wilderness.Application class to hold the main application.

  2. Adding one or more wilderness.Command objects for each of the subcommands, optionally organized into wilderness.Groups.

  3. Minor changes to setup.py to build the manpages.

Examples

Here are some examples that use Wilderness to build command line applications:

Repository Description
fakegit A multi-level command line application similar to Git
fakedf An application without subcommands similar to df
CleverCSV CleverCSV is a package for handling messy CSV files
Veld Easy command line analytics

Add your example here by opening a pull request!

Notes

License: See the LICENSE file.

Author: Gertjan van den Burg

wilderness's People

Contributors

baldurmen avatar gjjvdburg avatar martin-kokos avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

baldurmen

wilderness's Issues

Testsuite failure when running tests manually

When running the testsuite manually with python3 -m unittest discover, the discover argument is passed to the testsuite and makes it fail this way:

=== python3.9 ===
test_application_base (tests.test_application.ApplicationTestCase) ... ok
test_application_help_1 (tests.test_application.ApplicationTestCase) ... ok
test_application_help_2 (tests.test_application.ApplicationTestCase) ... ERROR
test_application_help_3 (tests.test_application.ApplicationTestCase) ... ERROR
test_application_help_4 (tests.test_application.ApplicationTestCase) ... ERROR
test_application_help_5 (tests.test_application.ApplicationTestCase) ... ERROR
test_application_help_6 (tests.test_application.ApplicationTestCase) ... ERROR
test__fill_text_1 (tests.test_formatter.HelpFormatterTestCase) ... ok
test__fill_text_2 (tests.test_formatter.HelpFormatterTestCase) ... ok
test__fill_text_3 (tests.test_formatter.HelpFormatterTestCase) ... ok
test__format_actions_usage_1 (tests.test_formatter.HelpFormatterTestCase) ... ok
test_group (tests.test_group.GroupTestCase) ... ok

======================================================================
ERROR: test_application_help_2 (tests.test_application.ApplicationTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python3.9/argparse.py", line 1869, in parse_known_args
    namespace, args = self._parse_known_args(args, namespace)
  File "/usr/lib/python3.9/argparse.py", line 2060, in _parse_known_args
    positionals_end_index = consume_positionals(start_index)
  File "/usr/lib/python3.9/argparse.py", line 2037, in consume_positionals
    take_action(action, args)
  File "/usr/lib/python3.9/argparse.py", line 1930, in take_action
    argument_values = self._get_values(action, argument_strings)
  File "/usr/lib/python3.9/argparse.py", line 2471, in _get_values
    self._check_value(action, value[0])
  File "/usr/lib/python3.9/argparse.py", line 2518, in _check_value
    raise ArgumentError(action, msg % args)
argparse.ArgumentError: argument command: invalid choice: 'discover' (choose from 'help')

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/tmp/autopkgtest.njn3t3/autopkgtest_tmp/tests/test_application.py", line 51, in test_application_help_2
    tester.test_application()
  File "/usr/lib/python3/dist-packages/wilderness/tester.py", line 82, in test_application
    self._retcode = self.application.run()
  File "/usr/lib/python3/dist-packages/wilderness/application.py", line 187, in run
    parsed_args = self._parser.parse_args(args=args, namespace=namespace)
  File "/usr/lib/python3.9/argparse.py", line 1836, in parse_args
    args, argv = self.parse_known_args(args, namespace)
  File "/usr/lib/python3.9/argparse.py", line 1872, in parse_known_args
    self.error(str(err))
  File "/usr/lib/python3.9/argparse.py", line 2593, in error
    self.exit(2, _('%(prog)s: error: %(message)s\n') % args)
  File "/usr/lib/python3/dist-packages/wilderness/parser.py", line 28, in exit
    sys.exit(status)
SystemExit: 2

Running tests this way is pretty standard, especially for distros like Debian where we tend to have automated templates to run tests during build.

0.1.9: pytest is failin because missing 'wilderness._argparse'

Looks like test suite is not up-to-date
Here is pytest output:

tests/test_formatter.py:15: in <module>
    from wilderness._argparse import ArgumentParser
E   ModuleNotFoundError: No module named 'wilderness._argparse'
=============================== warnings summary ===============================
wilderness/tester.py:23
  /home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/tester.py:23: PytestCollectionWarning: cannot collect test class 'Tester' because it has a __init__ constructor (from: tests/test
_application.py)
    class Tester:

tests/test_application.py:12
  /home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/tests/test_application.py:12: PytestCollectionWarning: cannot collect test class 'TestApp' because it has a __init__ constructor (from: test
s/test_application.py)
    class TestApp(Application):

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=========================== short test summary info ============================
ERROR tests/test_formatter.py
!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!
========================= 2 warnings, 1 error in 0.11s =========================

Remove the Application.handle method

It would be better to have a "root command" for applications that only have a single command, so we don't have to duplicate all the methods on the Application and the Command classes.

0.1.9: sphinx warnings `reference target not found`

First of all currently it is not possible to use straight sphinx-build command to build documentation out of source tree

+ /usr/bin/sphinx-build -n -T -b man docs build/sphinx/man
Running Sphinx v5.3.0
making output directory... done
WARNING: html_static_path entry 'source/_static' does not exist
building [mo]: targets for 0 po files that are out of date
building [man]: all manpages
updating environment: [new config] 7 added, 0 changed, 0 removed
reading sources... [100%] source/wilderness
WARNING: autodoc: failed to import module 'application' from module 'wilderness'; the following exception was raised:
No module named 'wilderness'
WARNING: autodoc: failed to import module 'command' from module 'wilderness'; the following exception was raised:
No module named 'wilderness'
WARNING: autodoc: failed to import module 'documentable' from module 'wilderness'; the following exception was raised:
No module named 'wilderness'
WARNING: autodoc: failed to import module 'formatter' from module 'wilderness'; the following exception was raised:
No module named 'wilderness'
WARNING: autodoc: failed to import module 'group' from module 'wilderness'; the following exception was raised:
No module named 'wilderness'
WARNING: autodoc: failed to import module 'help' from module 'wilderness'; the following exception was raised:
No module named 'wilderness'
WARNING: autodoc: failed to import module 'manpages' from module 'wilderness'; the following exception was raised:
No module named 'wilderness'
WARNING: autodoc: failed to import module 'tester' from module 'wilderness'; the following exception was raised:
No module named 'wilderness'
WARNING: autodoc: failed to import module 'wilderness'; the following exception was raised:
No module named 'wilderness'
looking for now-outdated files... none found
pickling environment... done
checking consistency... done
writing... python-wilderness.3 { _readme _changelog source/modules source/wilderness } done
build succeeded, 10 warnings.

This can be fixed by patch like below:

--- a/docs/conf.py
+++ b/docs/conf.py
@@ -13,8 +13,7 @@
 import os
 import sys

-sys.path.insert(0, os.path.abspath("."))
-
+sys.path.insert(0, os.path.abspath(".."))

 # -- Project information -----------------------------------------------------

This patch fixes what is in the comment and that can of fix is suggested in sphinx example copy.py https://www.sphinx-doc.org/en/master/usage/configuration.html#example-of-configuration-file

Than .. on building my packages I'm using sphinx-build command with -n switch which shows warmings about missing references. These are not critical issues.

Here is the output with warnings:

+ /usr/bin/sphinx-build -n -T -b man docs build/sphinx/man
Running Sphinx v5.3.0
making output directory... done
WARNING: html_static_path entry 'source/_static' does not exist
building [mo]: targets for 0 po files that are out of date
building [man]: all manpages
updating environment: [new config] 7 added, 0 changed, 0 removed
reading sources... [100%] source/wilderness
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/application.py:docstring of wilderness.application.Application:34: ERROR: Unknown target name: "fakedf".
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/application.py:docstring of wilderness.application.Application:50: ERROR: Unknown target name: "fakedf".
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/application.py:docstring of wilderness.application.Application:53: ERROR: Unknown target name: "fakedf".
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/application.py:docstring of wilderness.application.Application.handle:3: ERROR: Unknown target name: "fakedf".
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/application.py:docstring of wilderness.application.Application:34: ERROR: Unknown target name: "fakedf".
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/application.py:docstring of wilderness.application.Application:50: ERROR: Unknown target name: "fakedf".
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/application.py:docstring of wilderness.application.Application:53: ERROR: Unknown target name: "fakedf".
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/application.py:docstring of wilderness.application.Application.handle:3: ERROR: Unknown target name: "fakedf".
looking for now-outdated files... none found
pickling environment... done
checking consistency... done
writing... python-wilderness.3 { _readme _changelog source/modules source/wilderness } /home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/application.py:docstring of wilderness.application.Application:1: WARNING: py:class reference target not found: ..
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/application.py:docstring of wilderness.application.Application.add_argument:1: WARNING: py:class reference target not found: argparse.Action
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/application.py:docstring of wilderness.application.Application.add_mutually_exclusive_group:1: WARNING: py:class reference target not found: argparse._MutuallyExclusiveGroup
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/application.py:docstring of wilderness.application:1: WARNING: py:class reference target not found: command.Command
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/application.py:docstring of wilderness.application:4: WARNING: py:class reference target not found: group.Group
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/application.py:docstring of wilderness.application.Application.print_help:1: WARNING: py:obj reference target not found: typing.TextIO
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/application.py:docstring of wilderness.application.Application.print_help:1: WARNING: py:class reference target not found: TextIO
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/application.py:docstring of wilderness.application.Application.run:1: WARNING: py:class reference target not found: argparse.Namespace
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/application.py:docstring of wilderness.application.Application.run:1: WARNING: py:class reference target not found: argparse.Namespace
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/command.py:docstring of wilderness.command.Command.add_argument_group:1: WARNING: py:class reference target not found: wilderness._argparse.ArgumentGroup
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/command.py:docstring of wilderness.command.Command.add_mutually_exclusive_group:1: WARNING: py:class reference target not found: wilderness._argparse.MutuallyExclusiveGroup
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/command.py:docstring of wilderness.command.Command.application:1: WARNING: more than one target found for cross-reference 'Application': wilderness.application.Application, wilderness.Application
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/documentable.py:docstring of wilderness.documentable.DocumentableMixin.args:1: WARNING: py:class reference target not found: argparse.Namespace
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/documentable.py:docstring of wilderness.documentable.DocumentableMixin.parser:1: WARNING: py:class reference target not found: argparse.ArgumentParser
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/formatter.py:docstring of wilderness.formatter:1: WARNING: py:class reference target not found: argparse.HelpFormatter
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/group.py:docstring of wilderness.group.Group.add:1: WARNING: more than one target found for cross-reference 'Command': wilderness.command.Command, wilderness.Command
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/group.py:docstring of wilderness.group.Group.application:1: WARNING: more than one target found for cross-reference 'Application': wilderness.application.Application, wilderness.Application
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/group.py:docstring of wilderness.group.Group.commands:1: WARNING: more than one target found for cross-reference 'Command': wilderness.command.Command, wilderness.Command
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/group.py:docstring of wilderness.group.Group.commands_as_actions:1: WARNING: py:class reference target not found: argparse.Action
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/group.py:docstring of wilderness.group.Group.set_app:1: WARNING: more than one target found for cross-reference 'Application': wilderness.application.Application, wilderness.Application
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/help.py:docstring of wilderness.help.help_action_factory:1: WARNING: more than one target found for cross-reference 'Application': wilderness.application.Application, wilderness.Application
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/manpages.py:docstring of wilderness.manpages.build_manpages:1: WARNING: more than one target found for cross-reference 'Application': wilderness.application.Application, wilderness.Application
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/manpages.py:docstring of wilderness.manpages.build_manpages:1: WARNING: more than one target found for cross-reference 'Application': wilderness.application.Application, wilderness.Application
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/application.py:docstring of wilderness.application.Application:1: WARNING: py:class reference target not found: ..
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/application.py:docstring of wilderness.application.Application.add_argument:1: WARNING: py:class reference target not found: argparse.Action
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/application.py:docstring of wilderness.application.Application.add_mutually_exclusive_group:1: WARNING: py:class reference target not found: argparse._MutuallyExclusiveGroup
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/application.py:docstring of wilderness.application.Application.print_help:1: WARNING: py:obj reference target not found: typing.TextIO
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/application.py:docstring of wilderness.application.Application.print_help:1: WARNING: py:class reference target not found: TextIO
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/application.py:docstring of wilderness.application.Application.run:1: WARNING: py:class reference target not found: argparse.Namespace
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/application.py:docstring of wilderness.application.Application.run:1: WARNING: py:class reference target not found: argparse.Namespace
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/command.py:docstring of wilderness.command.Command.add_argument_group:1: WARNING: py:class reference target not found: wilderness._argparse.ArgumentGroup
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/command.py:docstring of wilderness.command.Command.add_mutually_exclusive_group:1: WARNING: py:class reference target not found: wilderness._argparse.MutuallyExclusiveGroup
/home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/group.py:docstring of wilderness.group.Group.commands_as_actions:1: WARNING: py:class reference target not found: argparse.Action
done
build succeeded, 42 warnings.

You can peak on fixes that kind of issues in other projects
latchset/jwcrypto#289
click-contrib/sphinx-click@abc31069
latchset/jwcrypto#289
RDFLib/rdflib-sqlalchemy#95
sissaschool/elementpath@bf869d9e
jaraco/cssutils#21
pywbem/pywbem#2895
sissaschool/xmlschema@42ea98f2
RDFLib/rdflib#2036
frostming/unearth#14
pypa/distlib@98b9b89f

Tag signed with different GPG key than CleverCSV?

Hi,

While working on packaging version 0.1.6 in Debian, I saw that you signed the git tag. Thanks a lot for this.

Sadly, it seems you signed it with a different key then the one you used for CleverCSV:

foo@bar:/tmp/wilderness$ git tag --verify v0.1.6 
object 61724e87a608e0c53a2fea31ba522436d34d4795
type commit
tag v0.1.6
tagger Gertjan van den Burg <[email protected]> 1650927673 +0100

Wilderness Release v0.1.6
gpg: Signature made lun 25 avr 2022 19:01:13 EDT
gpg:                using RSA key 7CC60619FFA032B86E150DC20B49E8D249BD109D
gpg:                issuer "[email protected]"
gpg: Can't check signature: No public key
foo@bar:/tmp/CleverCSV$ git tag --verify v0.7.4
object 003fc1e9f5d684dc131650c06af3e79d17bcbfa1
type commit
tag v0.7.4
tagger Gertjan van den Burg <[email protected]> 1652381700 +0100

CleverCSV Release v0.7.4
gpg: Signature made jeu 12 mai 2022 14:55:00 EDT
gpg:                using RSA key 2B73B22948BEA8293E5F00D543EA30C5B484F9AC
gpg: Can't check signature: No public key

Is this by design?

test_application_help_6 fails

Hi, I am getting the following test failure when packaging wilderness for Arch Linux:

......F......
======================================================================
FAIL: test_application_help_6 (tests.test_application.ApplicationTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/build/python-wilderness/src/wilderness-0.1.7/tests/test_application.py", line 81, in test_application_help_6
    self.assertEqual(tester.get_stdout(), self._helptext)
AssertionError: '' != 'usage: testapp [-h] [-q] command ...\n'
+ usage: testapp [-h] [-q] command ...


----------------------------------------------------------------------
Ran 13 tests in 0.005s

FAILED (failures=1)

Some environment info:
Python 3.10.6
Command: python -m unittest discover

0.1.9: pytest warnings

I'm packaging your module as an rpm package so I'm using the typical PEP517 based build, install and test cycle used on building packages from non-root account.

  • python3 -sBm build -w --no-isolation
  • because I'm calling build with --no-isolation I'm using during all processes only locally installed modules
  • install .whl file in </install/prefix>
  • run pytest with $PYTHONPATH pointing to sitearch and sitelib inside </install/prefix>
  • build is performed in env which is cut off from access to the public network (pytest is executed with -m "not network")

Here is pytest output:

+ PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-wilderness-0.1.9-2.fc35.x86_64/usr/lib64/python3.8/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-wilderness-0.1.9-2.fc35.x86_64/usr/lib/python3.8/site-packages
+ /usr/bin/pytest -ra -m 'not network'
==================================================================================== test session starts ====================================================================================
platform linux -- Python 3.8.16, pytest-7.2.1, pluggy-1.0.0
rootdir: /home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9
collected 14 items

tests/test_application.py ........                                                                                                                                                    [ 57%]
tests/test_formatter.py ....                                                                                                                                                          [ 85%]
tests/test_group.py ..                                                                                                                                                                [100%]

===================================================================================== warnings summary ======================================================================================
wilderness/tester.py:23
  /home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/wilderness/tester.py:23: PytestCollectionWarning: cannot collect test class 'Tester' because it has a __init__ constructor (from: tests/test_application.py)
    class Tester:

tests/test_application.py:12
  /home/tkloczko/rpmbuild/BUILD/wilderness-0.1.9/tests/test_application.py:12: PytestCollectionWarning: cannot collect test class 'TestApp' because it has a __init__ constructor (from: tests/test_application.py)
    class TestApp(Application):

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
============================================================================== 14 passed, 2 warnings in 0.06s ===============================================================================

Here is list of installed modules in build env

Package                       Version
----------------------------- -----------------
alabaster                     0.7.12
appdirs                       1.4.4
attrs                         22.2.0
Babel                         2.11.0
build                         0.9.0
charset-normalizer            3.0.1
contourpy                     1.0.6
cssselect                     1.1.0
cycler                        0.11.0
distro                        1.8.0
docutils                      0.19
exceptiongroup                1.0.0
extras                        1.0.0
fixtures                      4.0.0
fonttools                     4.38.0
gpg                           1.18.0-unknown
idna                          3.4
imagesize                     1.4.1
importlib-metadata            5.1.0
iniconfig                     1.1.1
Jinja2                        3.1.2
kiwisolver                    1.4.4
libcomps                      0.1.19
lxml                          4.9.1
MarkupSafe                    2.1.1
matplotlib                    3.6.3
numpy                         1.24.1
olefile                       0.46
packaging                     21.3
pbr                           5.9.0
pep517                        0.13.0
Pillow                        9.4.0
pip                           22.3.1
pluggy                        1.0.0
Pygments                      2.14.0
PyGObject                     3.42.2
pyparsing                     3.0.9
pytest                        7.2.1
python-dateutil               2.8.2
pytz                          2022.4
requests                      2.28.1
rpm                           4.17.0
scour                         0.38.2
setuptools                    65.6.3
six                           1.16.0
snowballstemmer               2.2.0
Sphinx                        5.3.0
sphinxcontrib-applehelp       1.0.2.dev20221204
sphinxcontrib-devhelp         1.0.2.dev20221204
sphinxcontrib-htmlhelp        2.0.0
sphinxcontrib-jsmath          1.0.1.dev20221204
sphinxcontrib-qthelp          1.0.3.dev20221204
sphinxcontrib-serializinghtml 1.1.5
testtools                     2.5.0
tomli                         2.0.1
urllib3                       1.26.12
wheel                         0.38.4
zipp                          3.11.0

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.