GithubHelp home page GithubHelp logo

pyudev / pyudev Goto Github PK

View Code? Open in Web Editor NEW
161.0 161.0 50.0 1.88 MB

Python bindings to libudev (with support for PyQt4, PySide, pygobject and wx)

Home Page: http://pyudev.readthedocs.org

License: GNU Lesser General Public License v2.1

Python 99.46% Makefile 0.54%

pyudev's Introduction

pyudev

pyudev is a LGPL licensed, pure Python binding for libudev, the device and hardware management and information library for Linux. It supports almost all libudev functionality. You can enumerate devices, query device properties and attributes or monitor devices, including asynchronous monitoring with threads, or within the event loops of Qt, Glib or wxPython.

The binding supports CPython 3 and compatible versions of PyPy. It is tested against udev 151 or newer, earlier versions of udev as found on dated Linux systems may work, but are not officially supported.

Usage

Usage of pyudev is quite simply thanks to the power of the underlying udev library. Getting the labels of all partitions just takes a few lines:

>>> import pyudev
>>> context = pyudev.Context()
>>> for device in context.list_devices(subsystem='block', DEVTYPE='partition'):
...     print(device.get('ID_FS_LABEL', 'unlabeled partition'))
...
boot
swap
system

The website provides a detailed user guide and a complete API reference.

Support

Please report issues and questions to the issue tracker, but respect the following guidelines:

  • Check that the issue has not already been reported.
  • Check that the issue is not already fixed in the master branch.
  • Open issues with clear title and a detailed description in grammatically correct, complete sentences.
  • Include the Python version and the udev version (see udevadm --version) in the description of your issue.

Development

The source code is hosted on GitHub:

git clone git://github.com/pyudev/pyudev.git

Please fork the repository and send pull requests with your fixes or new features, but respect the following guidelines:

Request a New Release

I will be doing regular releases of this project every August and October, shortly after Fedora releases are branched from rawhide.

If you believe an extra release would help you in some way, please file an issue, explaining why you need the new release, and I expect I'll put one up.

Why should you explain why you need the new release? Well, it is helpful to me, because pyudev is not at all part of my regular work, and I tend not to know very much about how it is used these days.

pyudev's People

Contributors

bgurney-rh avatar bnavigator avatar busytester avatar cjmayo avatar dashea avatar dwlehman avatar ffy00 avatar hide5stm avatar mulkieran avatar pyup-bot avatar s-t-e-v-e-n-k avatar skruppy avatar stephenfin avatar suyashbansal avatar swsnr avatar thijstriemstra avatar tobiasgehring avatar willemjan avatar z3ntu 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

pyudev's Issues

Improve tag interface

Wrap udev_device_has_tag, and use it to check for tags existence. Device.tags should return a new Tags object deriving from collections.Sequence and providing a container for tags.

Add a method to get the XID of a Device

When I do a xinput list I got:

⎡ Virtual core pointer                        id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
⎜   ↳ Logitech USB Laser Mouse                  id=8    [slave  pointer  (2)]
⎣ Virtual core keyboard                       id=3    [master keyboard (2)]
    ↳ Virtual core XTEST keyboard                 id=5    [slave  keyboard (3)]
    ↳ Power Button                                id=6    [slave  keyboard (3)]
    ↳ Power Button                                id=7    [slave  keyboard (3)]
    ↳ CHESEN USB Keyboard                         id=9    [slave  keyboard (3)]
    ↳ CHESEN USB Keyboard                         id=10   [slave  keyboard (3)]

My mouse id is 8 (So the XID of my mouse is 8).

But when I execute this Python code:

for device in pyudev.Context().list_devices(subsystem="input", ID_INPUT_MOUSE=True):
    if device.sys_name.startswith("event"):
        print "Device id is %s" % device.parent.device_number

I also tried to show all parent's attributes, but I can't find any one that match the XID.

Complete filter methods for Monitor

Wrap udev_monitor_add_match_tag() to filter by tags, and udev_monitor_filter_update() and udev_monitor_filter_remove().

The latter two should probably not be exported on the Monitor API, but instead only used internally to keep the Monitor filters in consistent state.

Create devices from environment

Add Device.from_environment, which creates a device object from the process environment, wrapping udev_device_new_from_environment. This allows to use pyudev-based scripts inside udev rules.

Will be very difficult to test.

Access to the device driver name

Add Device.driver property to get the name of the driver responsible for a device. Udev provides the driver name through udev_device_get_driver.

Support for initialization status

udev 166 gives access to initialization status of devices. Add support for this feature as soon as udev 166 is available.

This involves the following changes:

  • Wrap udev_device_get_is_initialized as Device.is_initialized property
  • Wrap udev_device_get_usec_since_initialized as Device.time_since_initialized or so. This should probably return a datetime.timedelta instead of the raw microseconds count.
  • Wrap udev_enumerate_add_match_is_initialized as Enumerator.match_initialized(), and probably also as initialized keyword to Enumerator.match() and Context.list_devices().

Implement Device.find_parent()

Add Device.find_parent() to find a parent device by subsystem and device type, atop of udev_get_parent_with_subsystem_devtype().

Need way of getting system attributes for a device

udev devices have system attributes (denoted by ATTR{x}=y where x is the attribute and y is the attribute's value) that are currently inaccessible from pyudev. libudev retrieves them using udev_device_get_sysattr_value().

Add sys number interface

Add Device.sys_number as wrapper for udev_device_get_sysnum(). Available on all supported libudev versions.

enumerate through context.list_devices() cause memory leak

I am using devices = context.list_devices(subsystem="usb") to get a list of usb devices, then go through each device. This operation causes memory leak. Please refer to program below,

#!/usr/bin/python
import pyudev
import gc

while True:
    context = pyudev.Context()
    devices = context.list_devices(subsystem="usb")
    for aDevice in devices:
         pass
    length = len(gc.garbage)
    print "garbage length: " + str(length)

Queue interface

Provide interface to the udev event queue as exposed by the udev_queue_* functions from libudev.

Rework MonitorObserver API

Just like #47, the MonitorObserver API needs to be reworked to remove the explicit action argument.

Implementation

  • Call the callback with the device only.
  • Wrap callbacks with two arguments in a closure that explicitly passes device.action as first argument.
  • ~~Emit a DeprecationWarning if a callback with two arguments is passed to MonitorObserver.~~~
  • Add callback argument taking a single argument.
  • Deprecate event_handler argument.

Use libudev for sysattr iteration

Use udev_device_get_sysattr_list_entry() (available in current udev master, and consequently starting with 167) instead of our custom logic to get a list of available sysattrs of a device in pyudev._core.Attributes

Test libudev signatures against libudev header

Verify the signatures of wrapped libudev functions in _libudev.py against the real signatures as declared in libudev.h.

  • Implement a libudev plugin that parses libudev.h with gccxml, extracts the list of available libudev functions and their signatures, wraps this data into a list of Function tuples and attaches this to pytest.config.libudev.
  • Provide libudev and libudev_function funcargs that provide the whole list of functions, or each libudev function respectively.

If gccxml is not available, attach an empty list to pytest.config.libudev, and make libudev and libudev_function funcargs skip the test. This will also fix the remaining part of #43.

Along with this change the whole test_libudev.h should be refactored.

pyudev.glib incompatible with Python 3

$ python2.7 -c 'import pyudev.glib'
$ python3.2 -c 'import pyudev.glib'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib64/python3.2/site-packages/pyudev/glib.py", line 40, in <module>
    from . import glib
ImportError: cannot import name glib

I use pygobject-2.28.6 with some patches backported from pygobject repository. This version of pygobject has been separately built and installed for each version of Python.

2to3 changed 'import glib' into 'from . import glib' during processing of pyudev/glib.py.
If I manually revert this change, then the following error occurs:

$ python3.2 -c 'import pyudev.glib'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib64/python3.2/site-packages/pyudev/glib.py", line 45, in <module>
    class GUDevMonitorObserver(gobject.GObject):
  File "/usr/lib64/python3.2/site-packages/gobject/__init__.py", line 60, in __init__
    cls._type_register(cls.__dict__)
  File "/usr/lib64/python3.2/site-packages/gobject/__init__.py", line 115, in _type_register
    type_register(cls, namespace.get('__gtype_name__'))
TypeError: __gsignals__ keys must be strings

pyside support

Implement QUDevMonitorObserver atop of PySide. #3 (new package structure) is mandatory prerequisite.

Remove dependency against global libudev object

Currently libudev is loaded on module level in pyudev._libudev, and all other modules use this module constant.

Disadvantages

  • Makes mock testing harder because the dependency is hidden and a global object needs to be patched.
  • Breaks import pyudev on non Linux systems.

Solution

  • Refactor pyudev so that each Context instance loads its own library object in __init__(), and all other classes access the libudev of their attached context.

Outcome

  • Mock testing is easier, because the libudev object of the per-test context can be patched.
  • Mock tests and tests that don't touch libudev can be run on non-Linux platforms.
  • Various tooling (i.e. documentation builds) or releases can be done on non-Linux platforms (i.e. OS X).

Link to dev docs

Add a link to the development documentation at readthedocs.org at an appropriate place (wherever this is ;) ).

Rework Monitor API

Rework Monitor-API.

Rationale

Returning multiple values from Monitor.receive_device and Monitor.__iter__ proved to be a bad idea, because it breaks the libudev API pattern to attach event attributes to the Device object and is thus hard to extend (see #10).

Implementation

  • Turn Monitor.start() into a separate method that keeps track of whether the monitor was already started, and is a nop in this case.
  • Add Monitor.started
  • Deprecate Monitor.enable_receiving() in favour of Monitor.start().
  • Add Monitor.poll(timeout=-1) to poll for new events using select.select() with the specified timeout. This method will only return a Device object and reference Device.action to extract the event action.
  • Deprecate Monitor.receive_device() in favor of Monitor.poll()
  • Deprecate Monitor.__iter__() and recommend explicit iteration of .poll() or MonitorObserver instead.

User guide

Write a decent user guide covering all important aspects of pyudev to replace the detailed information provided by the pyudev/__init__.py docstring. The API reference should then provide reference information mostly.

Add "Enumerator.match" as easy frontend for all the different match methods

Currently, more complex matches in Enumerator require a lot of method chaining. To easy matching add Enumerator.match(**kwargs) with the following API:

  • The keyword argument subsystem is equivalent to .match_subsystem().
  • The tag keyword is equivalent to .match_tag()
  • Any other keyword argument is equivalent to .match_property(), where the keyword argument is the property name and the argument value the property value.

match_property() do not seem to be ANDed

Hi,

I have checked out pyudev from git, and it seems to misbehave a bit:

list(udev.Context().list_devices().match_subsystem('block').match_property('ID_TYPE', 'disk'))

[Device(u'/sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda'), Device(u'/sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1')]

list(udev.Context().list_devices().match_subsystem('block').match_property('ID_TYPE', 'disk').match_property('DEVTYPE', 'disk'))

[Device(u'/sys/devices/pci0000:00/0000:00:1e.0/0000:03:01.0/host3/target3:0:0/3:0:0:0/block/sr0'), Device(u'/sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda'), Device(u'/sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1'), Device(u'/sys/devices/platform/floppy.0/block/fd0'), Device(u'/sys/devices/virtual/block/loop0'), Device(u'/sys/devices/virtual/block/loop1'), Device(u'/sys/devices/virtual/block/loop2'), Device(u'/sys/devices/virtual/block/loop3'), Device(u'/sys/devices/virtual/block/loop4'), Device(u'/sys/devices/virtual/block/loop5'), Device(u'/sys/devices/virtual/block/loop6'), Device(u'/sys/devices/virtual/block/loop7'), Device(u'/sys/devices/virtual/block/ram0'), Device(u'/sys/devices/virtual/block/ram1'), Device(u'/sys/devices/virtual/block/ram10'), Device(u'/sys/devices/virtual/block/ram11'), Device(u'/sys/devices/virtual/block/ram12'), Device(u'/sys/devices/virtual/block/ram13'), Device(u'/sys/devices/virtual/block/ram14'), Device(u'/sys/devices/virtual/block/ram15'), Device(u'/sys/devices/virtual/block/ram2'), Device(u'/sys/devices/virtual/block/ram3'), Device(u'/sys/devices/virtual/block/ram4'), Device(u'/sys/devices/virtual/block/ram5'), Device(u'/sys/devices/virtual/block/ram6'), Device(u'/sys/devices/virtual/block/ram7'), Device(u'/sys/devices/virtual/block/ram8'), Device(u'/sys/devices/virtual/block/ram9')]

I assume that second call to match_property should tighten the filter, not loosen it?

http://packages.python.org/pyudev/api.html#udev.Enumerator says:

All added filters must match for a device to be included in the device list, when eventually iterating over this object.

My git head is at 408c318.

bye,
Filip Zyzniewski

Provide device number interface

Add Device.device_number and Device.from_device_number as wrappers for udev_device_get_devnum and udev_device_new_from_devnum. Both of these are available on all supported udev versions.

Restructure udev APIs

Rename udev to pyudev and turn it into a package:

  • pyudev.__init__ contains __version__ and apipkg definitions for classes and submodules
  • pyudev._libudev contains ctypes wrapper code from _udev
  • pyudev._core contains Context and Device classes
  • pyudev._enumerate contains Enumerator class
  • pyudev._monitor contains Monitor class
  • pyudev._pyqt4 contains QUDevMonitorObserver class

All these classes and submodules are grouped in the following apipkg structure:

'Context': '._core.Context',
'Device': '._core.Device',
'Monitor': '._monitor.Monitor',
'Enumerator': '._enumerate.Enumerator',
'pyqt4': {
    'QUDevMonitorObserver': '._pyqt4.QUDevMonitorObserver'
},

Solving this issue is precondition for Python 3 support, because it de-couples to top-level package from implementation without loosing the comfortable namespace. This avoids imports of the API during installation phase, before 2to3 is run.

Remove deprecated API.

Remove all deprecated API.

Affected members

  • class Device:
    • traverse() (use ancestors instead)
  • class Monitor:
    • receive_device() (use poll() instead)
    • enable_receiving() (use start() instead)
    • __iter__() (use explicit looping with for event in iter(monitor.poll(), None) or asynchronous monitoring with MonitorObserver)

Test failures in pyudev 0.15

Some tests fail in pyudev 0.15. These tests were absent in pyudev 0.14. 2 of these tests fail only in Python 2.6.

$ py.test-2.6
============================= test session starts ==============================
platform linux2 -- Python 2.6.7 -- pytest-2.2.3
collected 619 items / 1 errors 

tests/test_core.py ........
tests/test_device.py ....................................s.s.ss.ss.s.s.ss.s.ssssssssssssssssssss.F...........ssssssssssssssssssssxxxxxx.xxx..........................................................................................................................................................................................................xx..xxxxx..............................................................................................................................................................................ssssssssss
tests/test_enumerate.py ..............ssssssssss.......s...
tests/test_monitor.py .........................s.s.s
tests/test_observer.py .............sss
tests/test_util.py ................F

==================================== ERRORS ====================================
____________________ ERROR collecting tests/test_libudev.py ____________________
tests/test_libudev.py:74: in pytest_generate_tests
>           for function in get_libudev_functions():
tests/test_libudev.py:54: in get_libudev_functions
>           check_call(['gccxml', LIBUDEV_H, '-fxml={0}'.format(stream.name)])
/usr/lib64/python2.6/subprocess.py:483: in check_call
>       retcode = call(*popenargs, **kwargs)
/usr/lib64/python2.6/subprocess.py:470: in call
>       return Popen(*popenargs, **kwargs).wait()
/usr/lib64/python2.6/subprocess.py:623: in __init__
>                           errread, errwrite)
/usr/lib64/python2.6/subprocess.py:1141: in _execute_child
>           raise child_exception
E           OSError: [Errno 2] No such file or directory
=================================== FAILURES ===================================
________________ TestDevice.test_from_device_file_non_existing _________________

self = <test_device.TestDevice object at 0x3393fd0>
context = <pyudev.core.Context object at 0x3296350>
tmpdir = local('/var/tmp/portage/dev-python/pyudev-0.15/temp/pytest-0/test_from_device_file_non_existing0')

    def test_from_device_file_non_existing(self, context, tmpdir):
        filename = tmpdir.join('test')
        assert not tmpdir.check(file=True)
        with pytest.raises(EnvironmentError) as excinfo:
            Device.from_device_file(context, str(filename))
>       assert excinfo.value.errno == errno.ENOENT
E       AttributeError: 'tuple' object has no attribute 'errno'

tests/test_device.py:170: AttributeError
______________________ test_get_device_type_not_existing _______________________

tmpdir = local('/var/tmp/portage/dev-python/pyudev-0.15/temp/pytest-0/test_get_device_type_not_existing0')

    def test_get_device_type_not_existing(tmpdir):
        filename = tmpdir.join('test')
        assert not tmpdir.check(file=True)
        with pytest.raises(EnvironmentError) as excinfo:
            _util.get_device_type(str(filename))
>       assert excinfo.value.errno == errno.ENOENT
E       AttributeError: 'tuple' object has no attribute 'errno'

tests/test_util.py:153: AttributeError
==== 2 failed, 523 passed, 78 skipped, 16 xfailed, 1 error in 25.84 seconds ====
$ py.test-2.7
============================= test session starts ==============================
platform linux2 -- Python 2.7.3 -- pytest-2.2.3
collected 619 items / 1 errors 

tests/test_core.py ........
tests/test_device.py ...................................ss.s.s.ssssss.s..s..s..s.sssssssssssssss.............ssssssssssssssssssssxxxxxxx.x...........................................................................................................................................................................................................x.xxxxx.x..............................................................................................................................................................................ssssssssss
tests/test_enumerate.py ..............ssssssssss.......s...
tests/test_monitor.py .........................s.s.s
tests/test_observer.py .............sss
tests/test_util.py .................

==================================== ERRORS ====================================
____________________ ERROR collecting tests/test_libudev.py ____________________
tests/test_libudev.py:74: in pytest_generate_tests
>           for function in get_libudev_functions():
tests/test_libudev.py:54: in get_libudev_functions
>           check_call(['gccxml', LIBUDEV_H, '-fxml={0}'.format(stream.name)])
/usr/lib64/python2.7/subprocess.py:506: in check_call
>       retcode = call(*popenargs, **kwargs)
/usr/lib64/python2.7/subprocess.py:493: in call
>       return Popen(*popenargs, **kwargs).wait()
/usr/lib64/python2.7/subprocess.py:679: in __init__
>                           errread, errwrite)
/usr/lib64/python2.7/subprocess.py:1249: in _execute_child
>           raise child_exception
E           OSError: [Errno 2] No such file or directory
========= 528 passed, 76 skipped, 15 xfailed, 1 error in 42.28 seconds =========

2to3 removal

Get rid of 2to3 completely, support Python 2 and 3 from the same code base and make pyudev installable with standard setuptools.

To do this, start with a diff of the 2to3 source and the actual source, identify differences and check whether these can be handled without 2to3 by means of refactoring the actual sources. This might ease testing and development, because the toolchain is less complicated, and might save us from 2to3 bugs like the one discovered in the fixing of #33.

Add `Device.from_node()`

Add a method to construct a Device object from a device node.

libudev doesn't provide means to do this directly, so we need to os.stat() the device file to determine its type (char or block device) and its major and minor device number. This information can then be passed to Device.from_device_number().

python 3 support

Support python 3 in pyudev. Requires the following steps:

  • Add python3 environment to tox.ini for testing
  • Use distribute to run 2to3 during installation (needs a bootstrapping file in source tree)

Cannot set the receive buffer size

Hello,

I came across some situations where pyudev would fail receiving an udev event, with the following error:

Traceback (most recent call last):
File "/usr/lib/python2.6/site-packages/pyudev/glib.py", line 92, in _process_udev_event
event = self.monitor.receive_device()
File "/usr/lib/python2.6/site-packages/pyudev/monitor.py", line 250, in receive_device
raise EnvironmentError(errno, os.strerror(errno))
EnvironmentError: [Errno 105] No buffer space available

There is a udev_monitor_set_receive_buffer_size in libudev, which allows setting the receive buffer size. It would be great if pyudev could export this method through pyudev.Monitor objects.

sysattr matching

Support matching by sysattrs (through udev_enumerate_add_match_sysattr()), available on all supported udev versions.

Access to tags

Add Device.tags property to access the tags attached to a device. libudev provides the tags through udev_device_get_tags_list_entry.

Access to the device number

Provide access to the monitor device number of a device. udev exposes this number through udev_device_get_devnum.

This should not be part of the Device API, because only devices created through a monitor have such a number. Instead Monitor.receive_device could probably get a third return value, which provides this number.

Permission errors in source tarball of 0.14

Just in case this isn't a problem with synaptiks, I'm going to submit a report here and then also to synpatiks developers.

Anyways, after upgrade from 0.13 to 0.14 synaptiks stopped working and outputted the following errors.

Traceback (most recent call last):
File "/usr/bin/synaptiks", line 5, in
from pkg_resources import load_entry_point
File "/usr/lib/python2.7/site-packages/pkg_resources.py", line 2727, in
add_activation_listener(lambda dist: dist.activate())
File "/usr/lib/python2.7/site-packages/pkg_resources.py", line 700, in subscribe
callback(dist)
File "/usr/lib/python2.7/site-packages/pkg_resources.py", line 2727, in
add_activation_listener(lambda dist: dist.activate())
File "/usr/lib/python2.7/site-packages/pkg_resources.py", line 2227, in activate
self.insert_on(path)
File "/usr/lib/python2.7/site-packages/pkg_resources.py", line 2334, in insert_on
self.check_version_conflict()
File "/usr/lib/python2.7/site-packages/pkg_resources.py", line 2373, in check_version_conflict
for modname in self._get_metadata('top_level.txt'):
File "/usr/lib/python2.7/site-packages/pkg_resources.py", line 2221, in _get_metadata
for line in self.get_metadata_lines(name):
File "/usr/lib/python2.7/site-packages/pkg_resources.py", line 1209, in get_metadata_lines
return yield_lines(self.get_metadata(name))
File "/usr/lib/python2.7/site-packages/pkg_resources.py", line 1201, in get_metadata
return self._get(self._fn(self.egg_info,name))
File "/usr/lib/python2.7/site-packages/pkg_resources.py", line 1316, in _get
stream = open(path, 'rb')
IOError: [Errno 13] Permission denied: '/usr/lib/python2.7/site-packages/pyudev-0.14-py2.7.egg-info/top_level.txt'

CI on travis-ci

travis-ci.org provides a sleek and apparently easy to use CI service triggered by GitHub hooks. Check out, if this service can be used for CI of pyudev.

Rework observer APIs

  • Add class MonitorObserver to all observer modules, with the same API, but without explicit actions in the signal or event arguments.
  • Add dedicated events for common actions.

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.