{"id":15442777,"url":"https://github.com/0x5ac/p2g","last_synced_at":"2026-02-27T10:38:03.748Z","repository":{"id":172590669,"uuid":"636988713","full_name":"0x5ac/p2g","owner":"0x5ac","description":"Python to G-Code transpiler","archived":false,"fork":false,"pushed_at":"2023-08-18T08:13:25.000Z","size":881,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-05T19:22:33.358Z","etag":null,"topics":["ast","cnc","g-code","gcode","haas","python","vf"],"latest_commit_sha":null,"homepage":"https://github.com/0x5ac/p2g","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/0x5ac.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"license.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-05-06T06:59:31.000Z","updated_at":"2025-03-16T02:19:37.000Z","dependencies_parsed_at":null,"dependency_job_id":"effaa492-4e00-4ed3-8a1b-b00b136c343d","html_url":"https://github.com/0x5ac/p2g","commit_stats":null,"previous_names":["0x5ac/p2g"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/0x5ac/p2g","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0x5ac%2Fp2g","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0x5ac%2Fp2g/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0x5ac%2Fp2g/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0x5ac%2Fp2g/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/0x5ac","download_url":"https://codeload.github.com/0x5ac/p2g/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0x5ac%2Fp2g/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29891895,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-27T09:48:51.284Z","status":"ssl_error","status_checked_at":"2026-02-27T09:48:43.992Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ast","cnc","g-code","gcode","haas","python","vf"],"created_at":"2024-10-01T19:30:02.737Z","updated_at":"2026-02-27T10:38:03.726Z","avatar_url":"https://github.com/0x5ac.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# P2G\n\n\u003cimg src=\"/docs/pytest.svg\" alt=\"\"\u003e\u003cimg src=\"/docs/mit.svg\" alt=\"\"\u003e\u003cimg src=\"/docs/coverage.svg\" alt=\"\"\u003e\n\u003cbr\u003e\n\u003cimg src=\"https://github.com/0x5ac/p2g/actions/workflows/make.yml/badge.svg\" alt=\"\"\u003e\n\n\n## Demo\n\n[![img](https://github.com/0x5ac/p2g/blob/main/docs/png/vicecenter1.png)](https://youtu.be/PX818-iRb1Q)\n\n\n## Introduction\n\n\n### Version 0.3.13\n\nP2G makes it simple to ensure that parts are in fixtures correctly, coordinate systems are adjusted to deal with stock placement and cope with movement and rotation of workpieces through multiple operations.\n\nP2G is a compiler; it takes Python code, some definitions of machine specific variables, a little glue and makes G-code, so far, Haas ideomatic.\n\nThanks to magic it can do surprising things with python data structures, anything reasonably calculated statically during compilation can be used in the source, classes, dicts, and so on.\n\nIt comes with a set of macro variable definitions for a Haas mill with NCD. And a few example settings for my own VF-3SSYT.\n\n\n## Install\n\n\n### From pypi\n\n```\n\n$ pip install p2g\n\n```\n\n\n### From github\n\n1.  fetch dependencies, rebuild and install with pip\n\n    ```\n    $ git clone https://github.com/0x5ac/p2g p2g\n    $ cd p2g\n    $ make install\n    ```\n\n2.  fetch dependencies and rebuild\n\n    ```\n    $ git clone https://github.com/0x5ac/p2g p2g\n    $ cd p2g\n    $ make\n    ```\n\n\n## Usage\n\n```\np2g - Turn Python into G-Code.\n\nUsage:\n  p2g [options]  \u003csrcfile\u003e [\u003cdstfile\u003e]\n  p2g help [ all | topics | maint | version | location | \u003ctopic\u003e ]\n  p2g build-examples \u003cdstdir\u003e\n\n       p2g tram-rotary.py ~/_nc_/O{countdown}tr.nc\n        Makes an output of the form ~/_nc_/O1234tr.nc\n\n       p2g --func=thisone -\n        Read from stdin, look for the 'thisone' function and write to\n        to stdout.\n\nArguments:\n  \u003csrcfile\u003e   Source python file.\n  \u003cdstfile\u003e   Destination G-Code file. [default: stdout]\n               {countdown} in file name creates a decrementing prefix\n               for the output file which makes looking for the .nc in\n               a crowded directory less painful - it's at the top.\n               (It's the number of seconds until midnight, so clear\n               the directory once a day.)\n  \u003ctopic\u003e      [ all | topics | maint | version | location | \u003ctopic\u003e ]\n         all      Print all readme.\n         topics   List all topics.\n         version  Show version\n         location Show absdir of main module.\n         \u003ctopic\u003e  Print from readme starting at topic.\n\nOptions:\n     --job=\u003cjobname\u003e      Olabel for output code.\n     --function=\u003cfname\u003e   Function to be compiled,\n                           default is last one in source file.\n     --narrow             Emit comments on their own line,\n                           makes text fit more easily into\n                           a narrow program window.\n     --short-filenames    Emit just the lsb of filenames.\n\n```\n\n\n## Examples\n\nfor a show:\n\n```\n$ p2g examples dstdir\n```\n\n---\n\n\n### Simple demo\n\necho \"\n\n```python\n\nimport p2g\ndef simple_demo():\n  x = p2g.Var(199)\n  for y in range(10):\n    x += y\n\n```\n\n\" ⇨ `directly` ⇨\n\n```\nO00001 (simple_demo: 0.3.13)\n  #100= 199.                      (   x = Var[199]                )\n  #102= 0.                        (   for y in range[10]:         )\nN1000\n  IF [#102 GE 10.] GOTO 1002      (   for y in range[10]:         )\n  #100= #100 + #102               ( x += y                        )\n  #102= #102 + 1.\n  GOTO 1000\nN1002\n  M30\n%\n```\n\n---\n\n\n### Find largest number of flutes in tool table\n\n```python\n\nimport p2g\n\n# stop with alarm code showing largest\n# flute count in table.\ndef maxflutes():\n\n    mx_flutes = p2g.Var(p2g.haas.TOOL_TBL_FLUTES[0])\n    for n_flutes in p2g.haas.TOOL_TBL_FLUTES[1:]:\n        if n_flutes \u003e mx_flutes:\n            mx_flutes = n_flutes\n\n    p2g.haas.MESSAGE.var = mx_flutes\n\n```\n\n⇨ `p2g maxflutes.py` ⇨\n\n```\nO00001 (maxflutes: 0.3.13)\n  #100= #1601                     ( mx_flutes = Var[haas.TOOL_TBL_FLUTES[0]])\n  #101= 1602.                     ( for n_flutes in haas.TOOL_TBL_FLUTES[1:]:)\nN1000\n  IF [#101 GE 1801.] GOTO 1002    ( for n_flutes in haas.TOOL_TBL_FLUTES[1:]:)\n  IF [#[#101] LE #100] GOTO 1003  (     if n_flutes \u003e mx_flutes:  )\n  #100= #[#101]                   (         mx_flutes = n_flutes  )\n  GOTO 1004\nN1003\nN1004\n  #101= #101 + 1.\n  GOTO 1000\nN1002\n  #3006= #100                     ( haas.MESSAGE.var = mx_flutes  )\n  M30\n%\n```\n\n---\n\n\n### Less trivial example\n\n```python\nfrom p2g import *\nfrom p2g.haas import *\nclass SearchParams:\n    def __init__(self, name, search_depth, iota, delta):\n        self.name = name\n        self.its = 10\n        self.search_depth = search_depth\n        self.iota = iota\n        self.delta = delta\n        self.probe = goto.probe.work.feed(30).all\n        self.go = goto.feed(640).work.all\n\n\ndef search(cursor, sch):\n    # stick from class SearchParams  iterations into macro var\n    its = Var(sch.its)\n    while its \u003e 0:\n        # goto start point\n        sch.go(cursor)\n        # down until hit - or not.\n        sch.probe(z=sch.search_depth)\n        # if probe is below (+some slack) hit\n        # point, then done.\n        if SKIP_POS.z \u003c sch.search_depth + sch.iota:\n            break\n        # otherwise move to next point\n        cursor.xy += sch.delta\n        its -= 1\n    else:\n        sys.message(ALARM[0], f\"too far {sch.name}.\")\n\n\ndef less_trivial():\n    cursor = Var[3](2, 3, 4)\n    # searching right, look down 0.4\", move\n    # 1.5\" right if nothing hit.\n    sch1 = SearchParams(name=\"right\", search_depth=-0.4, iota=-0.1, delta=(1.5, 0))\n    search(cursor, sch1)\n\n```\n\n⇨ `p2g less_trival.py` ⇨\n\n```\nO00001 (less_trivial: 0.3.13)\n  #100= 2.                        ( cursor = Var[3][2, 3, 4]      )\n  #101= 3.\n  #102= 4.\n  #103= 10.                       ( its = Var[sch.its]            )\nN1000\n  IF [#103 LE 0.] GOTO 1002       ( while its \u003e 0:                )\n(     sch.go[cursor]            )\n  G90 G01 G55 F640. x#100 y#101 z#102\n  G90 G31 G55 F30. z-0.4          (     sch.probe[z=sch.search_depth])\n  IF [#5063 LT -0.5] GOTO 1001    (     if SKIP_POS.z \u003c sch.search_depth + sch.iota:)\n  #100= #100 + 1.5                (     cursor.xy += sch.delta    )\n  #103= #103 - 1.                 (     its -= 1                  )\n  GOTO 1000\nN1002\n  #3000 = 101 (too far right.)\nN1001\n  M30\n%\n```\n\n\n# Table of contents\n\n\\*\n\n-   [Introduction](https://github.com/0x5ac/p2g/blob/main/docs/howto.md#introduction)\n-   [Variables](https://github.com/0x5ac/p2g/blob/main/docs/howto.md#variables)\n-   [Coordinates](https://github.com/0x5ac/p2g/blob/main/docs/howto.md#coordinates)\n-   [Expressions](https://github.com/0x5ac/p2g/blob/main/docs/howto.md#expressions)\n-   [Goto](https://github.com/0x5ac/p2g/blob/main/docs/howto.md#goto)\n-   [Axes](https://github.com/0x5ac/p2g/blob/main/docs/howto.md#axes)\n-   [When](https://github.com/0x5ac/p2g/blob/main/docs/howto.md#when)\n-   [DPRNT](https://github.com/0x5ac/p2g/blob/main/docs/howto.md#dprnt)\n-   [Symbol Tables](https://github.com/0x5ac/p2g/blob/main/docs/howto.md#symbol-table)\n-   [Notes](https://github.com/0x5ac/p2g/blob/main/docs/howto.md#notes)\n-   [Internal Options](https://github.com/0x5ac/p2g/blob/main/docs/howto.md#maitenance-options)\n-   [Authors](https://github.com/0x5ac/p2g/blob/main/docs/howto.md#authors)\n-   [Thanks](https://github.com/0x5ac/p2g/blob/main/docs/howto.md#thanks)\n\n-   Copyright © 2023 Steve Chamberlain","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0x5ac%2Fp2g","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F0x5ac%2Fp2g","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0x5ac%2Fp2g/lists"}