Coder Social home page Coder Social logo

Comments (13)

xBeo avatar xBeo commented on July 18, 2024 1

Thanks for the answer!

Yes, I'm wondering why installing all the other things works, but in this case I'm missing a permission.

What exactly do you mean with "playbook"? Isn't the playbook the bunch of files with the instructions for ansible? Or do you mean the install-custom.yml? That's the only file (besides the inventory) I (minorly) edited.

- hosts: rpi
  gather_facts: yes
  become: yes

  pre_tasks:
    - name: Install Python 3.x Ansible requirement
      raw: apt-get install -y python3
      changed_when: no
      tags:
        - always

  vars:
    prepi_pi_user: pi
    prepi_hostname: mycroft
    prepi_firmware_update: yes
    prepi_overclock: yes
    prepi_force_turbo: yes
    prepi_cpu_freq: 2000
    prepi_pulseaudio_daemon: yes
    
    mycroft_branch: dev
    mycroft_user: "{{ prepi_pi_user }}"
    mycroft_skills_update_interval: 2.0
    mycroft_recording_timeout_with_silence: 3.0
    mycroft_enclosure_name: picroft
    mycroft_extra_skills:
      - https://github.com/smartgic/mycroft-finished-booting-skill.git

  tasks:
    - import_role:
        name: smartgic.prepi
  
    - import_role:
        name: smartgic.mycroft

Or something else? Sorry, I'm really not familiar with ansible...

from ansible-playbooks-mycroft.

xBeo avatar xBeo commented on July 18, 2024 1

Thank you very much!
I'll try it this evening and write how it went.

from ansible-playbooks-mycroft.

xBeo avatar xBeo commented on July 18, 2024 1

Sooo...
The fix worked, but I had another error that I could solve myself this time though.
The Task "Allow localhost to communicate with port 8181" gave the Warning
[WARNING]: The value "8181" (type int) was converted to "'8181'" (type string). If this does not look like what you expect, quote the entire value to ensure it does not change.
and the Error
fatal: [rpi4b01]: FAILED! => {"changed": false, "msg": "Failed to find required executable iptables in paths: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"}

For the first I'm not exactly sure what to do, but I added quotes to the mycroft_bus_port variable in roles/smartgic.mycroft/vars, and the next time the warning didn't appear. I'm not sure about that fix though, maybe it wasn't nessecary. I ran it with the old value, just the number without the quotes, to be sure and it finished just fine.

The second one seemed to be missing iptables, and after installing it manually (sudo apt-get install iptables), it worked and the play finished without errors.

I guess my issue is closed with that, but maybe the last error could be fixed as well.

Thank you very much for the help. 😃

from ansible-playbooks-mycroft.

goldyfruit avatar goldyfruit commented on July 18, 2024

Hi,

According to the error message, you have a permission denied. Could you please paste your playbook?

from ansible-playbooks-mycroft.

goldyfruit avatar goldyfruit commented on July 18, 2024

An Ansible playbook is list of actions to perform (tasks, roles, etc...), what you pasted above 👍

@xBeo I found the issue in the code... It fixed.

Prior the playbook re-run, could you please run this command to update the smartgic.mycroft role on your computer:

ansible-galaxy install smartgic.mycroft --force

from ansible-playbooks-mycroft.

xBeo avatar xBeo commented on July 18, 2024

The fix seems to work, the TASK [smartgic.mycroft : Install Python packages] doesn't give an error anymore, though it always already has the status "ok".

Sadly two tasks later [Create Mycroft AI virtualenv] there's another error. This time the error message is quite long.

TASK [smartgic.mycroft : Create Mycroft AI virtualenv] *************************************************************************************************************************************************************************************
fatal: [rpi4b01]: FAILED! => {"changed": false, "cmd": ["/home/pi/mycroft-core/.venv/bin/pip3", "install", "-r", "/home/pi/mycroft-core/requirements/requirements.txt"], "msg": "stdout: Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple\nCollecting requests~=2.26.0\n  Downloading https://www.piwheels.org/simple/requests/requests-2.26.0-py2.py3-none-any.whl (62 kB)\nCollecting gTTS<2.3.0,>=2.2.2\n  Downloading gTTS-2.2.4-py3-none-any.whl (26 kB)\nCollecting PyAudio==0.2.11\n  Downloading PyAudio-0.2.11.tar.gz (37 kB)\nCollecting pyee==8.1.0\n  Downloading https://www.piwheels.org/simple/pyee/pyee-8.1.0-py2.py3-none-any.whl (12 kB)\nCollecting SpeechRecognition==3.8.1\n  Downloading SpeechRecognition-3.8.1-py2.py3-none-any.whl (32.8 MB)\nCollecting tornado~=6.1\n  Downloading tornado-6.1-cp39-cp39-manylinux2014_aarch64.whl (427 kB)\nCollecting websocket-client~=1.2.1\n  Downloading https://www.piwheels.org/simple/websocket-client/websocket_client-1.2.3-py3-none-any.whl (53 kB)\nCollecting requests-futures==0.9.5\n  Downloading https://www.piwheels.org/simple/requests-futures/requests_futures-0.9.5-py3-none-any.whl (6.7 kB)\nCollecting pyserial==3.0\n  Downloading https://www.piwheels.org/simple/pyserial/pyserial-3.0-py3-none-any.whl (87 kB)\nCollecting psutil==5.6.6\n  Downloading psutil-5.6.6.tar.gz (447 kB)\nCollecting pocketsphinx==0.1.0\n  Downloading pocketsphinx-0.1.0.zip (723 kB)\nCollecting pillow==8.3.2\n  Downloading Pillow-8.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (3.0 MB)\nCollecting python-dateutil==2.6.0\n  Downloading https://www.piwheels.org/simple/python-dateutil/python_dateutil-2.6.0-py2.py3-none-any.whl (194 kB)\nCollecting fasteners==0.14.1\n  Downloading https://www.piwheels.org/simple/fasteners/fasteners-0.14.1-py2.py3-none-any.whl (20 kB)\nCollecting PyYAML==5.4\n  Downloading PyYAML-5.4.tar.gz (174 kB)\n  Installing build dependencies: started\n  Installing build dependencies: finished with status 'done'\n  Getting requirements to build wheel: started\n  Getting requirements to build wheel: finished with status 'done'\n    Preparing wheel metadata: started\n    Preparing wheel metadata: finished with status 'done'\nCollecting lingua-franca==0.4.2\n  Downloading https://www.piwheels.org/simple/lingua-franca/lingua_franca-0.4.2-py3-none-any.whl (591 kB)\nCollecting msm==0.8.9\n  Downloading https://www.piwheels.org/simple/msm/msm-0.8.9-py3-none-any.whl (25 kB)\nCollecting msk==0.3.16\n  Downloading https://www.piwheels.org/simple/msk/msk-0.3.16-py3-none-any.whl (47 kB)\nCollecting mycroft-messagebus-client==0.9.4\n  Downloading https://www.piwheels.org/simple/mycroft-messagebus-client/mycroft_messagebus_client-0.9.4-py3-none-any.whl (16 kB)\nCollecting adapt-parser==0.5.1\n  Downloading adapt_parser-0.5.1-py3-none-any.whl (29 kB)\nCollecting padatious==0.4.8\n  Downloading https://www.piwheels.org/simple/padatious/padatious-0.4.8-py2.py3-none-any.whl (24 kB)\nCollecting fann2==1.0.7\n  Downloading fann2-1.0.7.tar.gz (63 kB)\nCollecting padaos==0.1.9\n  Downloading https://www.piwheels.org/simple/padaos/padaos-0.1.9-py3-none-any.whl (3.1 kB)\nCollecting precise-runner==0.2.1\n  Downloading https://www.piwheels.org/simple/precise-runner/precise_runner-0.2.1-py3-none-any.whl (5.2 kB)\nCollecting petact==0.1.2\n  Downloading https://www.piwheels.org/simple/petact/petact-0.1.2-py3-none-any.whl (4.3 kB)\nCollecting pyxdg==0.27\n  Downloading https://www.piwheels.org/simple/pyxdg/pyxdg-0.27-py2.py3-none-any.whl (49 kB)\nRequirement already satisfied: six>=1.10.0 in /usr/lib/python3/dist-packages (from adapt-parser==0.5.1->-r /home/pi/mycroft-core/requirements/requirements.txt (line 21)) (1.16.0)\nCollecting monotonic>=0.1\n  Downloading https://www.piwheels.org/simple/monotonic/monotonic-1.6-py2.py3-none-any.whl (5.3 kB)\nCollecting GitPython>=3.0.5\n  Downloading https://www.piwheels.org/simple/gitpython/GitPython-3.1.27-py3-none-any.whl (181 kB)\nRequirement already satisfied: colorama in /usr/lib/python3/dist-packages (from msk==0.3.16->-r /home/pi/mycroft-core/requirements/requirements.txt (line 19)) (0.4.4)\nCollecting pygithub\n  Downloading https://www.piwheels.org/simple/pygithub/PyGithub-1.55-py3-none-any.whl (291 kB)\nCollecting pako\n  Downloading https://www.piwheels.org/simple/pako/pako-0.3.1-py3-none-any.whl (16 kB)\nCollecting lazy\n  Downloading https://www.piwheels.org/simple/lazy/lazy-1.4-py2.py3-none-any.whl (6.2 kB)\nCollecting xxhash\n  Downloading xxhash-3.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (241 kB)\nRequirement already satisfied: click in /usr/lib/python3/dist-packages (from gTTS<2.3.0,>=2.2.2->-r /home/pi/mycroft-core/requirements/requirements.txt (line 2)) (7.1.2)\nRequirement already satisfied: urllib3<1.27,>=1.21.1 in /usr/lib/python3/dist-packages (from requests~=2.26.0->-r /home/pi/mycroft-core/requirements/requirements.txt (line 1)) (1.26.5)\nCollecting charset-normalizer~=2.0.0\n  Downloading https://www.piwheels.org/simple/charset-normalizer/charset_normalizer-2.0.12-py3-none-any.whl (44 kB)\nRequirement already satisfied: certifi>=2017.4.17 in /usr/lib/python3/dist-packages (from requests~=2.26.0->-r /home/pi/mycroft-core/requirements/requirements.txt (line 1)) (2020.6.20)\nRequirement already satisfied: idna<4,>=2.5 in /usr/lib/python3/dist-packages (from requests~=2.26.0->-r /home/pi/mycroft-core/requirements/requirements.txt (line 1)) (2.10)\nCollecting gitdb<5,>=4.0.1\n  Downloading https://www.piwheels.org/simple/gitdb/gitdb-4.0.9-py3-none-any.whl (63 kB)\nCollecting smmap<6,>=3.0.1\n  Downloading https://www.piwheels.org/simple/smmap/smmap-5.0.0-py3-none-any.whl (24 kB)\nCollecting appdirs\n  Downloading https://www.piwheels.org/simple/appdirs/appdirs-1.4.4-py2.py3-none-any.whl (9.6 kB)\nCollecting deprecated\n  Downloading https://www.piwheels.org/simple/deprecated/Deprecated-1.2.13-py2.py3-none-any.whl (9.5 kB)\nRequirement already satisfied: pyjwt>=2.0 in /usr/lib/python3/dist-packages (from pygithub->msk==0.3.16->-r /home/pi/mycroft-core/requirements/requirements.txt (line 19)) (2.1.0)\nCollecting pynacl>=1.4.0\n  Downloading PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl (601 kB)\nCollecting cffi>=1.4.1\n  Downloading cffi-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (447 kB)\nCollecting pycparser\n  Downloading https://www.piwheels.org/simple/pycparser/pycparser-2.21-py2.py3-none-any.whl (119 kB)\nRequirement already satisfied: wrapt<2,>=1.10 in /usr/lib/python3/dist-packages (from deprecated->pygithub->msk==0.3.16->-r /home/pi/mycroft-core/requirements/requirements.txt (line 19)) (1.12.1)\nBuilding wheels for collected packages: fann2, pocketsphinx, psutil, PyAudio, PyYAML\n  Building wheel for fann2 (setup.py): started\n  Building wheel for fann2 (setup.py): finished with status 'done'\n  Created wheel for fann2: filename=fann2-1.0.7-cp39-cp39-linux_aarch64.whl size=348592 sha256=e05005a1b6701382197722c93bcca94762339153e60998a764b899cf07bca174\n  Stored in directory: /home/pi/.cache/pip/wheels/1d/46/20/2db71cba21cab544af045f1cad5d5356d48c8359cdd3c05494\n  Building wheel for pocketsphinx (setup.py): started\n  Building wheel for pocketsphinx (setup.py): still running...\n  Building wheel for pocketsphinx (setup.py): finished with status 'done'\n  Created wheel for pocketsphinx: filename=pocketsphinx-0.1.0-cp39-cp39-linux_aarch64.whl size=1658867 sha256=04ada39990f6c6c52812405ac13e75580b5d0b0e61148883d9c5b6e78a825f8b\n  Stored in directory: /home/pi/.cache/pip/wheels/d5/38/73/43f0b13857297ec9955e7e0535d0a65b10e78e2942b16f19d9\n  Building wheel for psutil (setup.py): started\n  Building wheel for psutil (setup.py): finished with status 'done'\n  Created wheel for psutil: filename=psutil-5.6.6-cp39-cp39-linux_aarch64.whl size=267635 sha256=1b5dcaee6f3b1ec4a9b9c31f0ed94d3851595ed54b742306398b8330cb556896\n  Stored in directory: /home/pi/.cache/pip/wheels/eb/72/4d/913d867e29ad11af7fc8fd7a39e495f5e02afbd89415bb61df\n  Building wheel for PyAudio (setup.py): started\n  Building wheel for PyAudio (setup.py): finished with status 'done'\n  Created wheel for PyAudio: filename=PyAudio-0.2.11-cp39-cp39-linux_aarch64.whl size=50665 sha256=39d3f49a54da3fb56511e0cf837484270d895a79429f39cab4154b65ae02c0c5\n  Stored in directory: /home/pi/.cache/pip/wheels/76/e7/d6/193c174cc4cba9409e8eecea8f9e986fc9c88e08160759dfe8\n  Building wheel for PyYAML (PEP 517): started\n  Building wheel for PyYAML (PEP 517): finished with status 'error'\nSuccessfully built fann2 pocketsphinx psutil PyAudio\nFailed to build PyYAML\n\n:stderr:   ERROR: Command errored out with exit status 1:\n   command: /home/pi/mycroft-core/.venv/bin/python3 /tmp/tmp9b5mr6_2_in_process.py build_wheel /tmp/tmpn_md8hjk\n       cwd: /tmp/pip-install-fskbrrik/pyyaml_278b8d39141c46dab1d6b4d1397484f4\n  Complete output (83 lines):\n  running bdist_wheel\n  running build\n  running build_py\n  creating build\n  creating build/lib.linux-aarch64-3.9\n  creating build/lib.linux-aarch64-3.9/yaml\n  copying lib3/yaml/tokens.py -> build/lib.linux-aarch64-3.9/yaml\n  copying lib3/yaml/serializer.py -> build/lib.linux-aarch64-3.9/yaml\n  copying lib3/yaml/scanner.py -> build/lib.linux-aarch64-3.9/yaml\n  copying lib3/yaml/resolver.py -> build/lib.linux-aarch64-3.9/yaml\n  copying lib3/yaml/representer.py -> build/lib.linux-aarch64-3.9/yaml\n  copying lib3/yaml/reader.py -> build/lib.linux-aarch64-3.9/yaml\n  copying lib3/yaml/parser.py -> build/lib.linux-aarch64-3.9/yaml\n  copying lib3/yaml/nodes.py -> build/lib.linux-aarch64-3.9/yaml\n  copying lib3/yaml/loader.py -> build/lib.linux-aarch64-3.9/yaml\n  copying lib3/yaml/events.py -> build/lib.linux-aarch64-3.9/yaml\n  copying lib3/yaml/error.py -> build/lib.linux-aarch64-3.9/yaml\n  copying lib3/yaml/emitter.py -> build/lib.linux-aarch64-3.9/yaml\n  copying lib3/yaml/dumper.py -> build/lib.linux-aarch64-3.9/yaml\n  copying lib3/yaml/cyaml.py -> build/lib.linux-aarch64-3.9/yaml\n  copying lib3/yaml/constructor.py -> build/lib.linux-aarch64-3.9/yaml\n  copying lib3/yaml/composer.py -> build/lib.linux-aarch64-3.9/yaml\n  copying lib3/yaml/__init__.py -> build/lib.linux-aarch64-3.9/yaml\n  creating build/lib.linux-aarch64-3.9/_yaml\n  copying lib3/_yaml/__init__.py -> build/lib.linux-aarch64-3.9/_yaml\n  running build_ext\n  creating build/temp.linux-aarch64-3.9\n  creating build/temp.linux-aarch64-3.9/yaml\n  aarch64-linux-gnu-gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -ffile-prefix-map=/build/python3.9-PN012d/python3.9-3.9.2=. -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -fPIC -I/home/pi/mycroft-core/.venv/include -I/usr/include/python3.9 -c yaml/_yaml.c -o build/temp.linux-aarch64-3.9/yaml/_yaml.o\n  In file included from yaml/_yaml.c:696:\n  yaml/_yaml.h:2:10: fatal error: yaml.h: No such file or directory\n      2 | #include <yaml.h>\n        |          ^~~~~~~~\n  compilation terminated.\n  Error compiling module, falling back to pure Python\n  running install\n  running install_lib\n  Traceback (most recent call last):\n    File \"/tmp/tmp9b5mr6_2_in_process.py\", line 280, in <module>\n      main()\n    File \"/tmp/tmp9b5mr6_2_in_process.py\", line 263, in main\n      json_out['return_val'] = hook(**hook_input['kwargs'])\n    File \"/tmp/tmp9b5mr6_2_in_process.py\", line 204, in build_wheel\n      return _build_backend().build_wheel(wheel_directory, config_settings,\n    File \"/usr/lib/python3/dist-packages/setuptools/build_meta.py\", line 216, in build_wheel\n      return self._build_with_temp_dir(['bdist_wheel'], '.whl',\n    File \"/usr/lib/python3/dist-packages/setuptools/build_meta.py\", line 202, in _build_with_temp_dir\n      self.run_setup()\n    File \"/usr/lib/python3/dist-packages/setuptools/build_meta.py\", line 145, in run_setup\n      exec(compile(code, __file__, 'exec'), locals())\n    File \"setup.py\", line 271, in <module>\n      setup(\n    File \"/usr/lib/python3/dist-packages/setuptools/__init__.py\", line 153, in setup\n      return distutils.core.setup(**attrs)\n    File \"/usr/lib/python3/dist-packages/setuptools/_distutils/core.py\", line 148, in setup\n      dist.run_commands()\n    File \"/usr/lib/python3/dist-packages/setuptools/_distutils/dist.py\", line 967, in run_commands\n      self.run_command(cmd)\n    File \"/usr/lib/python3/dist-packages/setuptools/_distutils/dist.py\", line 986, in run_command\n      cmd_obj.run()\n    File \"/usr/lib/python3/dist-packages/wheel/bdist_wheel.py\", line 259, in run\n      self.run_command('install')\n    File \"/usr/lib/python3/dist-packages/setuptools/_distutils/cmd.py\", line 313, in run_command\n      self.distribution.run_command(command)\n    File \"/usr/lib/python3/dist-packages/setuptools/_distutils/dist.py\", line 986, in run_command\n      cmd_obj.run()\n    File \"/usr/lib/python3/dist-packages/setuptools/command/install.py\", line 61, in run\n      return orig.install.run(self)\n    File \"/usr/lib/python3/dist-packages/setuptools/_distutils/command/install.py\", line 578, in run\n      self.run_command(cmd_name)\n    File \"/usr/lib/python3/dist-packages/setuptools/_distutils/cmd.py\", line 313, in run_command\n      self.distribution.run_command(command)\n    File \"/usr/lib/python3/dist-packages/setuptools/_distutils/dist.py\", line 985, in run_command\n      cmd_obj.ensure_finalized()\n    File \"/usr/lib/python3/dist-packages/setuptools/_distutils/cmd.py\", line 107, in ensure_finalized\n      self.finalize_options()\n    File \"/usr/lib/python3/dist-packages/setuptools/command/install_lib.py\", line 17, in finalize_options\n      self.set_undefined_options('install',('install_layout','install_layout'))\n    File \"/usr/lib/python3/dist-packages/setuptools/_distutils/cmd.py\", line 290, in set_undefined_options\n      setattr(self, dst_option, getattr(src_cmd_obj, src_option))\n    File \"/usr/lib/python3/dist-packages/setuptools/_distutils/cmd.py\", line 103, in __getattr__\n      raise AttributeError(attr)\n  AttributeError: install_layout\n  ----------------------------------------\n  ERROR: Failed building wheel for PyYAML\nERROR: Could not build wheels for PyYAML which use PEP 517 and cannot be installed directly\n"}

PLAY RECAP *********************************************************************************************************************************************************************************************************************************
rpi4b01                    : ok=59   changed=38   unreachable=0    failed=1    skipped=2    rescued=0    ignored=0   

Screenshot_Error_Anible_Mycroft

Is this another issue, or a consequence of the same issue? It seems to concern python as well after all. I also tried installing pythonyaml manually, since that's the only thing I could get from the message, but it didn't change anything.

from ansible-playbooks-mycroft.

goldyfruit avatar goldyfruit commented on July 18, 2024

I think the issue is related to wheel, the one provided by Debian seems to be an issue.

I updated the role, by using pip to install the wheel library.

As before, run this command prior:

ansible-galaxy install smartgic.mycroft --force

I hope it will help, thanks for your help.

from ansible-playbooks-mycroft.

xBeo avatar xBeo commented on July 18, 2024

Sadly I'm getting the same error. I ran the command, but it was the same result.

from ansible-playbooks-mycroft.

goldyfruit avatar goldyfruit commented on July 18, 2024

Sadly I'm getting the same error. I ran the command, but it was the same result.

I'm able to reproduce the error, I'll look for a fix.

from ansible-playbooks-mycroft.

goldyfruit avatar goldyfruit commented on July 18, 2024

I opened an issue on mycroft-core.

The issue is related to PyYAML 5.4, installing version 5.4.1 seems to fix the issue.

from ansible-playbooks-mycroft.

goldyfruit avatar goldyfruit commented on July 18, 2024

I just pushed a fixed with the commit 4e486cac3e62ec43152145372e2beb1891a3eb45

As before, run this command prior:

ansible-galaxy install smartgic.mycroft --force

I hope it will help, thanks for your patience. 👍

from ansible-playbooks-mycroft.

goldyfruit avatar goldyfruit commented on July 18, 2024

A PR from @gez should be merged very soon, from there the workaround I did yesterday will not be necessary anymore.

from ansible-playbooks-mycroft.

goldyfruit avatar goldyfruit commented on July 18, 2024

@xBeo The first is just a warning, the second one is fixed. 👍

Thanks again!

from ansible-playbooks-mycroft.

Related Issues (4)

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.