libs.zazac.link
Libs/capy/config.json

capy.config.json v0.5.4

Le fichier qui décrit tout un projet capy : son nom, comment joindre le serveur (local, wifi ou internet), le chiffrement, et les fichiers du projet

Inclus dans capy : installe capy pour l'avoir.

import capy · PyPI : capyy · Python 3.9+

Le guide

Le fichier qui décrit tout un projet capy : son nom, comment joindre le serveur (local, wifi ou internet), le chiffrement, et les fichiers du projet. Le serveur et le client le lisent avec capy.project(), et la commande cy lance ses scripts et ses fichiers, comme npm avec package.json.

Le fichier complet#

Toutes les clés sont facultatives, sauf celles que demande le mode (port en local, relay en network).

capy.config.json
{
    "$schema": "https://libs.zazac.link/capy.config.schema.json",
    "name": "mon-jeu",
    "description": "Un petit jeu en réseau",
    "version": "1.0",
    "author": "Izac",
    "mode": "local",
    "url": "127.0.0.1",
    "port": 2388,
    "tls": true,
    "files": {
        "server": "server.py",
        "client": "client.py",
        "admin": "outils/admin.py"
    },
    "scripts": {
        "start": "cy run",
        "test": "python3 -m unittest discover -s tests",
        "deploy": "rsync -az . mon-vps:/srv/mon-jeu/"
    }
}

Toutes les clés#

CléTypePourPar défaut
$schematextel'adresse du schéma, pour l'autocomplétion de VS Code (capy l'ignore)—
nametextele nom du projet ; c'est aussi le nom du serveur en wifi et en networkle nom du dossier
descriptiontexteune phrase sur le projet—
versiontextela version du projet, ex : "1.0"—
authortextequi a fait le projet—
modetexte"local", "wifi" ou "network""network" s'il y a un relay, sinon "local"
urltextel'adresse du serveur pour le client, avec le port si tu veux : "127.0.0.1:2388""localhost"
hosttextepareil que url, sans le port (mets l'un ou l'autre, pas les deux)"localhost"
portnombrele port du serveur ; 0 = un port libre au hasardobligatoire en local
tlsoui / nonle chiffrementtrue
relaytextele relais capy.network : "mon-vps.fr:3879"obligatoire en network
keytextela clé du relais (mieux : "$CAPY_KEY")—
fingerprinttextel'empreinte du relais, affichée à son démarrage—
filesobjetles fichiers du projet, par nom : {"server": "server.py"}—
scriptsobjetdes commandes avec un nom, comme dans package.json : {"test": "python3 -m unittest"}—

Les trois modes#

local : sur la même machine, ou vers une IP connue#

capy.config.json
{
    "name": "mon-jeu",
    "mode": "local",
    "url": "127.0.0.1:2388"
}

Le serveur écoute sur le port 2388 ; le client appelle 127.0.0.1:2388. Pour qu'un autre ordi joigne le serveur, mets l'IP du serveur dans url (ex : "192.168.1.42:2388") dans le fichier du client.

wifi : par un nom, sur le même wifi#

capy.config.json
{
    "name": "salon",
    "mode": "wifi"
}

Pas d'IP ni de port : le serveur s'annonce sous le nom salon, le client le trouve tout seul. Un port reste possible si tu veux toujours le même.

network : à travers internet, par un relais#

capy.config.json
{
    "name": "maison",
    "mode": "network",
    "relay": "mon-vps.fr:3879",
    "key": "$CAPY_KEY",
    "fingerprint": "9b734c758696262e758f8664db40fafe3601f3804ced5dc331527704319f3049"
}

Le serveur se connecte au relais sous le nom maison ; le client l'appelle par ce nom, depuis n'importe où. Toujours chiffré : "tls": false est refusé. Voir le guide de capy.network pour installer le relais.

Écrire les valeurs#

capy convertit tout seul

  • "port": 2388 ou "port": "2388" : les deux marchent.
  • "tls" accepte true / false, et en texte "True", "oui", "non", "yes", "no", "1", "0", "on", "off" (majuscules ou pas).
  • "url": "127.0.0.1:2388" donne l'adresse et le port.

Les secrets : $VARIABLE#

Un texte qui commence par $ est lu dans les variables d'environnement. Marche pour toutes les clés, même dans files.

capy.config.json
{ "name": "maison", "relay": "$CAPY_RELAY", "key": "$CAPY_KEY" }
~/.zshrc
export CAPY_RELAY='mon-vps.fr:3879'
export CAPY_KEY='ma-longue-cle-secrete'

Partager le projet sans la clé

Avec $CAPY_KEY, la vraie clé n'est jamais dans le fichier : tu peux mettre le projet sur GitHub ou l'envoyer à quelqu'un. Il lui suffira de mettre sa propre clé dans son ~/.zshrc.

Les fichiers : files#

files donne un nom à chaque fichier du projet. Les chemins partent du **dossier de capy.config.json**, et ~ marche aussi.

json
"files": {
    "server": "server.py",
    "client": "client.py",
    "admin": "outils/admin.py",
    "tests": "tests/test_jeu.py"
}
  • cy server, cy client, cy admin… lancent le fichier de ce nom.
  • cy run utilise server et client.
  • Dans le code : app.file("admin") donne le chemin complet, et app.files tous les fichiers.

Les commandes : scripts#

Comme les scripts de package.json chez npm : tu donnes un nom à une commande du terminal, et cy NOM la lance, depuis le dossier du projet, où que tu sois.

json
"scripts": {
    "start": "cy run",
    "test": "python3 -m unittest discover -s tests",
    "format": "python3 -m black .",
    "deploy": "rsync -az --exclude .git . mon-vps:/srv/mon-jeu/",
    "salut": "echo Bonjour depuis $CAPY_NAME, port $CAPY_PORT"
}
terminal
cy test
résultat
> python3 -m unittest discover -s tests
....
Ran 4 tests in 0.012s
OK
  • La commande passe par le shell : &&, |, > et les $VARIABLES marchent comme dans le terminal.
  • python3 (ou python) au début est remplacé par le Python qui lance capy : pas de surprise entre deux Python installés.
  • cy au début ("start": "cy run") lance capy avec ce même Python, même si cy n'est pas dans le PATH.
  • Les arguments en plus sont ajoutés à la fin : cy test -k login lance … discover -s tests -k login.
  • Le script reçoit les infos du projet en variables d'environnement : CAPY_NAME, CAPY_MODE, CAPY_PROJECT (le dossier), et en mode local CAPY_HOST et CAPY_PORT.
  • Le code de sortie du script devient celui de cy : un script qui échoue fait échouer la commande.
  • cy scripts les liste. Dans le code : app.scripts et app.run_script("test").

Enchaîner des scripts

Un script peut en lancer d'autres : "check": "cy format && cy test".

Des noms réservés

init, new, run, scripts et help sont des commandes de capy : un script ne peut pas s'appeler comme ça (capy le dit au chargement). Et si un script et un fichier de files ont le même nom, c'est le script qui gagne.

Où capy cherche le fichier#

capy.project() cherche capy.config.json :

  1. dans le dossier du script lancé (pas celui du terminal) ;
  2. puis dans les dossiers au-dessus, jusqu'à la racine (comme git).

Un client/client.py ou un outils/admin.py trouvent donc le fichier du projet. cy, lui, part du dossier du terminal. Pour un autre fichier : capy.project("autre.json") ou capy.project("~/projets/jeu").

Dans le code#

python
import capy

app = capy.project()

app.name, app.version, app.author, app.description   # Les infos du projet
app.mode, app.host, app.port, app.tls                # Comment le joindre
app.folder                                           # Le dossier du projet
app.file("server")                                   # Le chemin d'un fichier de "files"
print(app.describe())                                # Tout, en texte (comme cy)

server = app.server()                                # Côté serveur : déjà réglé
reponse = app.call("hello", nom="Izac")              # Côté client : sans IP ni port

Les erreurs#

capy vérifie tout le fichier au chargement et dit quoi corriger :

Dans le fichierLe message
"prot": 4000clé 'prot' inconnue dans capy.config.json (tu voulais dire 'port' ?)
"port": "abc"'port' doit être un nombre dans capy.config.json (reçu 'abc')
"tls": "peut-etre"'tls' doit être true ou false dans capy.config.json (reçu 'peut-etre')
"url": "http://127.0.0.1"capy ne parle pas HTTP, écris juste l'adresse dans capy.config.json (ex : '127.0.0.1')
"url": "127.0.0.1:9999" et "port": 2388deux ports différents dans capy.config.json ('127.0.0.1:9999' et "port": 2388)
"host" et "url" ensemblemets "host" ou "url" dans capy.config.json, pas les deux
mode local sans portil manque "port" dans capy.config.json (ex : "port": 4000)
mode network sans relaisil manque "relay" dans capy.config.json (ex : "relay": "mon-vps.fr:3879")
"key": "$CAPY_KEY" sans la variablela variable d'environnement CAPY_KEY n'existe pas (ajoute export CAPY_KEY='...' dans ~/.zshrc)
une virgule en tropcapy.config.json n'est pas du JSON valide (…)

Le JSON n'accepte pas tout

Pas de virgule après le dernier élément, des guillemets doubles partout ("port", pas 'port'), et pas de commentaires. Avec le schéma (juste en dessous), VS Code souligne ces erreurs en rouge.

L'autocomplétion dans VS Code#

Ajoute la ligne "$schema" en haut du fichier : VS Code propose alors les clés, explique chacune au survol, et souligne les erreurs (mauvais mode, port en texte bizarre, clé inconnue…) pendant que tu écris.

capy.config.json
{
    "$schema": "https://libs.zazac.link/capy.config.schema.json",
    "name": "mon-jeu"
}

Déjà là avec new et init

capy new et capy init écrivent la ligne "$schema" pour toi.

Les commandes#

**cy est la commande d'un projet capy : elle s'installe avec capy, et ne marche que dans un projet** (un dossier qui a un capy.config.json, ou un de ses sous-dossiers). Pour créer un projet, c'est capy new ou capy init.

cy, capy et python3 -m capy

cy sert dans un projet ; capy sert partout (créer un projet, capy domo, capy relay) et sait aussi tout ce que fait cy. Si une commande n'est pas trouvée (« command not found »), c'est que le dossier des commandes de pip n'est pas dans ton PATH : python3 -m capy … fait exactement la même chose que capy ….

CommandeCe qu'elle fait
cymontre le projet : nom, version, mode, adresse, fichiers (✓ s'ils existent)
capy new NOM [mode]crée un dossier NOM avec capy.config.json, server.py, client.py
capy init [nom] [mode]crée juste capy.config.json dans le dossier actuel
cy server / client / NOMlance ce fichier de files (les arguments en plus lui sont passés)
cy runserveur en fond + client, puis arrête le serveur
cy NOM [args…]lance le script NOM de scripts (avant un fichier du même nom)
cy scriptsliste les scripts
cy call ACTION [nom=valeur…]appelle une action du serveur du projet (local, wifi ou relais, selon le fichier)
capy cli / cy clile mode interactif : les commandes à la suite, avec historique et complétion (Tab)
capy versionla version de capy
capy call HÔTE:PORT ACTION [nom=valeur…]appelle une action de n'importe quel serveur capy (--no-tls s'il est en clair)
capy wifi scan / capy wifi call NOM ACTION …les serveurs du wifi : les lister, en appeler un
capy network call NOM ACTION … [--relay …] [--key …]appeler un serveur par internet, via un relais
capy domo …la domotique : voir capy.domo
capy relay PORT [CLÉ]lance un relais capy.network (sur le VPS)
résultat
$ cy
mon-jeu v1.0 par Izac
  Un petit jeu en réseau
  mode     local (127.0.0.1:2388)
  tls      oui (chiffré)
  server   server.py  ✓
  client   client.py  ✓
  admin    outils/admin.py  ✗ introuvable
  script   start    cy run
  script   test     python3 -m unittest discover -s tests
  fichier  /Users/izac/projets/mon-jeu/capy.config.json

Exemples

Un projet complet : capy.config.json

On décrit le projet une fois (nom, version, port, adresse, chiffrement, fichiers…) ; serveur et client le lisent avec capy.project(), et cy lance ses scripts et ses fichiers (comme npm).

1. Créer le projet (modes : local, wifi ou network), puis tout lancer d'un coup

creer_le_projet.sh
capy new mon-jeu
cd mon-jeu
cy          # Voir ce que capy a compris
# mon-jeu v1.0
#   mode     local (localhost:4000)
#   tls      oui (chiffré)
#   server   server.py  ✓
#   client   client.py  ✓

cy run      # Serveur en fond + client, puis arrêt du serveur
# server │ API en écoute sur le port 4000, chiffrée (TLS) · empreinte : …
# Bonjour toi !

cy server   # Ou chacun dans son terminal
cy client

capy.domo à distance : la maison devient un serveur capy

Sur l'ordi qui reste à la maison. Avec un capy.config.json, c'est son mode (local, wifi ou network) qui est utilisé : avec "relay", la maison est pilotable depuis tout internet. Sans, un serveur capy sur le port 4040.

maison.py
import capy.domo

capy.domo.serve()  # Actions domo.list, domo.state, domo.set, domo.toggle, domo.scene