ts2python


Namets2python JSON
Version 0.7.3 PyPI version JSON
download
home_pagehttps://github.com/jecki/ts2python
SummaryPython-Interoperability for Typescript-Interfaces
upload_time2024-01-29 21:54:40
maintainer
docs_urlNone
authorEckhart Arnold
requires_python>=3.7,<4.0
licenseApache-2.0
keywords typescript to python converter typescript interface python typeddict
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # ts2python

![](https://img.shields.io/pypi/v/ts2python) 
![](https://img.shields.io/pypi/status/ts2python) 
![](https://img.shields.io/pypi/pyversions/ts2python) 
![](https://img.shields.io/pypi/l/ts2python)
[![Stand With Ukraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/badges/StandWithUkraine.svg)](https://stand-with-ukraine.pp.ua)


Python-interoperability for Typescript-Interfaces.
Transpiles TypeScript-Interface-definitions to Python 
TypedDicts, plus support for run-time type-checking 
of JSON-data.

## License and Source Code

ts2python is open source software under the [Apache 2.0 License](https://www.apache.org/licenses/LICENSE-2.0)

Copyright 2021-2023 Eckhart Arnold <arnold@badw.de>, Bavarian Academy of Sciences and Humanities

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

The complete source-code of ts2python can be downloaded from the 
[git-repository](https://github.com/jecki/ts2python).

## Purpose

When processing JSON data, as for example, form a 
[JSON-RPC](https://www.jsonrpc.org/) call, with Python, it would
be helpful to have Python-definitions of the JSON-structures at
hand, in order to solicit IDE-Support, static type checking and,
potentially to enable structural validation at runtime. 

There exist different technologies for defining the structure of
JSON-data. Next to [JSON-schema](http://json-schema.org/), a 
de facto very popular technology for defining JSON-obejcts are
[Typescript-Interfaces](https://www.typescriptlang.org/docs/handbook/2/objects.html). 
For example, the 
[language server protocol](https://microsoft.github.io/language-server-protocol/specifications/specification-current/) 
defines the structure of the JSON-data exchanged between client 
and server with Typescript-Interfaces.

In order to enable structural validation on the Python-side, 
ts2python transpiles the typescript-interface definitions
to Python-data structure definitions, primarily, 
[TypedDicts](https://www.python.org/dev/peps/pep-0589/),
but with some postprocessing it can also be adjusted to
other popular models for records or data structures in
Python, e.g.
[pydantic](https://pydantic-docs.helpmanual.io/)-Classes
and the like.

ts2python aims to support translation of TypeScript-Interfaces on two
different tiers:

1. *Tier 1: Transpilation of passive data-structures*, that is, 
   Typescript-definition-files that contain only data definitions 
   and no function definitions and, in particular,
   only "passive" Typescript-Interface that define data-structures 
   but do not contain any methods.

2. *Tier 2: Tanspilation of active data-structures, function- 
   and method-definitions*, i.e. Translation of (almost) any
   Typescript-definition-file.

## Status

Presently, Tier 1 support, i.e. transpilation of passive data 
structures works quite well. So, for example, all Interfaces
from the
[language server protocol V3.16](https://microsoft.github.io/language-server-protocol/specifications/specification-3-16/) 
can be transpiled to Python Typed-Dicts. 

Tier 2 support is still very much work in progress. I am 
using "vscode.d.ts"-definition file as test-case. Some things work,
but there are still some unsupported constructs, and the Python
code emitted for features that go beyond Tier 1 may not even
be valid Python all the time! Please, keep that in mind.

The documentation presently only covers Tier 1 support. 


## Installation

ts2python can be installed from the command line with the command:

    $ pip install ts2python

ts2python requires the parsing-expression-grammar-framework 
[DHParser](https://gitlab.lrz.de/badw-it/DHParser)
which will automatically be installed as a dependency by 
the `pip`-command. ts2python requires at least Python Version 3.8
to run. (If there is any interest, I might backport it to Python 3.6.)
However, the Python-code it produces is backwards compatible 
down to Python 3.6, if the 
[typing extensions](https://pypi.org/project/typing-extensions/) 
have been installed.

## Usage

In order to generate TypedDict-classes from Typescript-Interfaces,
run `ts2python` on the Typescript-Interface definitions:

    $ ts2python interfaces.ts

This generates a .py-file in same directory as the source
file that contains the TypedDict-classes and can simpy be 
imported in Python-Code:

    from interfaces import *

Json-data which adheres to a specific structure (no matter
whether defined on the typescript side via interfaces or
on the Python-side via TypedDicts) can easily be interchanged
and deserialized:

    import json
    request_msg: RequestMessage = json.loads(input_data)

The root-type (``RootMessage`` in the above example) can
be arbitrarily complex and deeply nested.

**Calling ts2python from another Python-script**:

The ts2python-Parser can, of course, also be accessed directly
from Python with the followin imports and function calls:

    from ts2python.ts2pthonParser import process_file
    ...
    process_file("SOURCE.ts", "DESTINATION.py")

Or, use:

    from ts2pthon.ts2pythonParser import compile_src, serialize_result
    ...
    result, errors = compile_src(DOCUMENT)
    if errors:
        for e in errors:  print(e)
    else:
       print(serialize_result(result))


## Validation

ts2python ships support for runtime-type validation. While type
errors can be detected by static type checkers, runtime type 
validation can be useful when processing data from an outside
source which cannot statically be checked, like, for example,
json-data stemming from an RPC-call. ts2python runtime-type
validation can be invoked via dedicated functions or via
decorator as in this example:

    from ts2python.json_validation import TypedDict, type_check

    class Position(TypedDict, total=True):
        line: int
        character: int 

    class Range(TypedDict, total=True):
        start: Position
        end: Position

    @type_check
    def middle_line(rng: Range) -> Position:
        line = (rng['start']['line'] + rng['end']['line']) // 2
        character = 0
        return Position(line=line, character=character)

    data = {'start': {'line': 1, 'character': 1},
           'end': {'line': 8, 'character': 17}}
    assert middle_line(data) == {'line': 4, 'character': 0}

    malformed_data = {'start': 1, 'end': 8}
    middle_line(malformed_data)  # <- TypeError raised by @type_check 

With the type decorator the last call fails with a TypeError:

    TypeError: Parameter "rng" of function "middle_line" failed the type-check, because:
    Type error(s) in dictionary of type <class '__main__.Range'>:
    Field start: '1' is not of <class '__main__.Position'>, but of type <class 'int'>
    Field end: '8' is not of <class '__main__.Position'>, but of type <class 'int'>

Both the call and the return types can be validated.

## Type Checkers

The output ts2python is somewhat more liberal than what strict
typecheckers like mypy or pylance seem to allow. In particular
class definitions inside TypedDicts are considered illegal by
the specification und thus marked as an error by some 
type-checkers. Use the command-line switch "-a toplevel" to
generate Python-code that is more acceptable to type checkers.

## Full Documentation

See [ts2python.readthedocs.io](https://ts2python.readthedocs.io) for the comprehensive
documentation of ts2python


## Tests and Demonstration

The [git-repository of ts2python](https://github.com/jecki/ts2python) contains unit-tests 
as well as [doctests](https://docs.python.org/3/library/doctest.html).
After cloning ts2python from the git-repository with:

    $ git clone https://github.com/jecki/ts2python

the unit tests can be found in the `tests` subdirectory. 
Both the unit and the doctests can be run by changing to the 
`tests`-sub-directory and calling the `runner.py`-skript therein. 

    $ cd tests
    $ python runner.py

It is also possible to run the tests with [pytest](https://docs.pytest.org/) 
or [nose](https://nose.readthedocs.io), in case you have
either of theses testing-frameworks installed.

For a demonstration how the TypeScript-Interfaces are transpiled
to Python-code, run the `demo-3-16.sh`-script (or `demo-3-16.bat` on Windows)
in the "demo"-sub-directory or the ts2python-repository. 

(Presently, this does not work with the LSP 3.17 specs, because the
specs contain typescript bugs at a few places and thus would need to 
be corrected by hand after downloading.)

Or, run the `tst_ts2python_grammar.py` in the ts2python-directory
and look up the grammar-test-reports in the "REPORT"-sub-directory 
of the "test_grammar"-subdirectory.

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/jecki/ts2python",
    "name": "ts2python",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.7,<4.0",
    "maintainer_email": "",
    "keywords": "Typescript to Python converter,Typescript Interface,Python TypedDict",
    "author": "Eckhart Arnold",
    "author_email": "eckhart.arnold@posteo.de",
    "download_url": "https://files.pythonhosted.org/packages/62/fb/0656025a3d203f3935a55aca0ad4385c51d4ec6df220059e5bd89e147193/ts2python-0.7.3.tar.gz",
    "platform": null,
    "description": "# ts2python\n\n![](https://img.shields.io/pypi/v/ts2python) \n![](https://img.shields.io/pypi/status/ts2python) \n![](https://img.shields.io/pypi/pyversions/ts2python) \n![](https://img.shields.io/pypi/l/ts2python)\n[![Stand With Ukraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/badges/StandWithUkraine.svg)](https://stand-with-ukraine.pp.ua)\n\n\nPython-interoperability for Typescript-Interfaces.\nTranspiles TypeScript-Interface-definitions to Python \nTypedDicts, plus support for run-time type-checking \nof JSON-data.\n\n## License and Source Code\n\nts2python is open source software under the [Apache 2.0 License](https://www.apache.org/licenses/LICENSE-2.0)\n\nCopyright 2021-2023 Eckhart Arnold <arnold@badw.de>, Bavarian Academy of Sciences and Humanities\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nThe complete source-code of ts2python can be downloaded from the \n[git-repository](https://github.com/jecki/ts2python).\n\n## Purpose\n\nWhen processing JSON data, as for example, form a \n[JSON-RPC](https://www.jsonrpc.org/) call, with Python, it would\nbe helpful to have Python-definitions of the JSON-structures at\nhand, in order to solicit IDE-Support, static type checking and,\npotentially to enable structural validation at runtime. \n\nThere exist different technologies for defining the structure of\nJSON-data. Next to [JSON-schema](http://json-schema.org/), a \nde facto very popular technology for defining JSON-obejcts are\n[Typescript-Interfaces](https://www.typescriptlang.org/docs/handbook/2/objects.html). \nFor example, the \n[language server protocol](https://microsoft.github.io/language-server-protocol/specifications/specification-current/) \ndefines the structure of the JSON-data exchanged between client \nand server with Typescript-Interfaces.\n\nIn order to enable structural validation on the Python-side, \nts2python transpiles the typescript-interface definitions\nto Python-data structure definitions, primarily, \n[TypedDicts](https://www.python.org/dev/peps/pep-0589/),\nbut with some postprocessing it can also be adjusted to\nother popular models for records or data structures in\nPython, e.g.\n[pydantic](https://pydantic-docs.helpmanual.io/)-Classes\nand the like.\n\nts2python aims to support translation of TypeScript-Interfaces on two\ndifferent tiers:\n\n1. *Tier 1: Transpilation of passive data-structures*, that is, \n   Typescript-definition-files that contain only data definitions \n   and no function definitions and, in particular,\n   only \"passive\" Typescript-Interface that define data-structures \n   but do not contain any methods.\n\n2. *Tier 2: Tanspilation of active data-structures, function- \n   and method-definitions*, i.e. Translation of (almost) any\n   Typescript-definition-file.\n\n## Status\n\nPresently, Tier 1 support, i.e. transpilation of passive data \nstructures works quite well. So, for example, all Interfaces\nfrom the\n[language server protocol V3.16](https://microsoft.github.io/language-server-protocol/specifications/specification-3-16/) \ncan be transpiled to Python Typed-Dicts. \n\nTier 2 support is still very much work in progress. I am \nusing \"vscode.d.ts\"-definition file as test-case. Some things work,\nbut there are still some unsupported constructs, and the Python\ncode emitted for features that go beyond Tier 1 may not even\nbe valid Python all the time! Please, keep that in mind.\n\nThe documentation presently only covers Tier 1 support. \n\n\n## Installation\n\nts2python can be installed from the command line with the command:\n\n    $ pip install ts2python\n\nts2python requires the parsing-expression-grammar-framework \n[DHParser](https://gitlab.lrz.de/badw-it/DHParser)\nwhich will automatically be installed as a dependency by \nthe `pip`-command. ts2python requires at least Python Version 3.8\nto run. (If there is any interest, I might backport it to Python 3.6.)\nHowever, the Python-code it produces is backwards compatible \ndown to Python 3.6, if the \n[typing extensions](https://pypi.org/project/typing-extensions/) \nhave been installed.\n\n## Usage\n\nIn order to generate TypedDict-classes from Typescript-Interfaces,\nrun `ts2python` on the Typescript-Interface definitions:\n\n    $ ts2python interfaces.ts\n\nThis generates a .py-file in same directory as the source\nfile that contains the TypedDict-classes and can simpy be \nimported in Python-Code:\n\n    from interfaces import *\n\nJson-data which adheres to a specific structure (no matter\nwhether defined on the typescript side via interfaces or\non the Python-side via TypedDicts) can easily be interchanged\nand deserialized:\n\n    import json\n    request_msg: RequestMessage = json.loads(input_data)\n\nThe root-type (``RootMessage`` in the above example) can\nbe arbitrarily complex and deeply nested.\n\n**Calling ts2python from another Python-script**:\n\nThe ts2python-Parser can, of course, also be accessed directly\nfrom Python with the followin imports and function calls:\n\n    from ts2python.ts2pthonParser import process_file\n    ...\n    process_file(\"SOURCE.ts\", \"DESTINATION.py\")\n\nOr, use:\n\n    from ts2pthon.ts2pythonParser import compile_src, serialize_result\n    ...\n    result, errors = compile_src(DOCUMENT)\n    if errors:\n        for e in errors:  print(e)\n    else:\n       print(serialize_result(result))\n\n\n## Validation\n\nts2python ships support for runtime-type validation. While type\nerrors can be detected by static type checkers, runtime type \nvalidation can be useful when processing data from an outside\nsource which cannot statically be checked, like, for example,\njson-data stemming from an RPC-call. ts2python runtime-type\nvalidation can be invoked via dedicated functions or via\ndecorator as in this example:\n\n    from ts2python.json_validation import TypedDict, type_check\n\n    class Position(TypedDict, total=True):\n        line: int\n        character: int \n\n    class Range(TypedDict, total=True):\n        start: Position\n        end: Position\n\n    @type_check\n    def middle_line(rng: Range) -> Position:\n        line = (rng['start']['line'] + rng['end']['line']) // 2\n        character = 0\n        return Position(line=line, character=character)\n\n    data = {'start': {'line': 1, 'character': 1},\n           'end': {'line': 8, 'character': 17}}\n    assert middle_line(data) == {'line': 4, 'character': 0}\n\n    malformed_data = {'start': 1, 'end': 8}\n    middle_line(malformed_data)  # <- TypeError raised by @type_check \n\nWith the type decorator the last call fails with a TypeError:\n\n    TypeError: Parameter \"rng\" of function \"middle_line\" failed the type-check, because:\n    Type error(s) in dictionary of type <class '__main__.Range'>:\n    Field start: '1' is not of <class '__main__.Position'>, but of type <class 'int'>\n    Field end: '8' is not of <class '__main__.Position'>, but of type <class 'int'>\n\nBoth the call and the return types can be validated.\n\n## Type Checkers\n\nThe output ts2python is somewhat more liberal than what strict\ntypecheckers like mypy or pylance seem to allow. In particular\nclass definitions inside TypedDicts are considered illegal by\nthe specification und thus marked as an error by some \ntype-checkers. Use the command-line switch \"-a toplevel\" to\ngenerate Python-code that is more acceptable to type checkers.\n\n## Full Documentation\n\nSee [ts2python.readthedocs.io](https://ts2python.readthedocs.io) for the comprehensive\ndocumentation of ts2python\n\n\n## Tests and Demonstration\n\nThe [git-repository of ts2python](https://github.com/jecki/ts2python) contains unit-tests \nas well as [doctests](https://docs.python.org/3/library/doctest.html).\nAfter cloning ts2python from the git-repository with:\n\n    $ git clone https://github.com/jecki/ts2python\n\nthe unit tests can be found in the `tests` subdirectory. \nBoth the unit and the doctests can be run by changing to the \n`tests`-sub-directory and calling the `runner.py`-skript therein. \n\n    $ cd tests\n    $ python runner.py\n\nIt is also possible to run the tests with [pytest](https://docs.pytest.org/) \nor [nose](https://nose.readthedocs.io), in case you have\neither of theses testing-frameworks installed.\n\nFor a demonstration how the TypeScript-Interfaces are transpiled\nto Python-code, run the `demo-3-16.sh`-script (or `demo-3-16.bat` on Windows)\nin the \"demo\"-sub-directory or the ts2python-repository. \n\n(Presently, this does not work with the LSP 3.17 specs, because the\nspecs contain typescript bugs at a few places and thus would need to \nbe corrected by hand after downloading.)\n\nOr, run the `tst_ts2python_grammar.py` in the ts2python-directory\nand look up the grammar-test-reports in the \"REPORT\"-sub-directory \nof the \"test_grammar\"-subdirectory.\n",
    "bugtrack_url": null,
    "license": "Apache-2.0",
    "summary": "Python-Interoperability for Typescript-Interfaces",
    "version": "0.7.3",
    "project_urls": {
        "Homepage": "https://github.com/jecki/ts2python",
        "Repository": "https://github.com/jecki/ts2python"
    },
    "split_keywords": [
        "typescript to python converter",
        "typescript interface",
        "python typeddict"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "ceae162e3ce1c341ecd6b54dad15dada29ba76b35e1c1027c2f78d2cd7344019",
                "md5": "a5f9cd5682f95e00c625bc48a596aa2c",
                "sha256": "fee34aa42e77dbbe9d93b731f3831c56464a5f3cddf33b92fffb63ada62c0385"
            },
            "downloads": -1,
            "filename": "ts2python-0.7.3-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "a5f9cd5682f95e00c625bc48a596aa2c",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7,<4.0",
            "size": 67879,
            "upload_time": "2024-01-29T21:54:38",
            "upload_time_iso_8601": "2024-01-29T21:54:38.204550Z",
            "url": "https://files.pythonhosted.org/packages/ce/ae/162e3ce1c341ecd6b54dad15dada29ba76b35e1c1027c2f78d2cd7344019/ts2python-0.7.3-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "62fb0656025a3d203f3935a55aca0ad4385c51d4ec6df220059e5bd89e147193",
                "md5": "41588b540b334bfb5af8bf979b30c28d",
                "sha256": "ff6679b65c1906d03658e4795f7d7e40d1b62fe00f71d2bacd3fd95e86575412"
            },
            "downloads": -1,
            "filename": "ts2python-0.7.3.tar.gz",
            "has_sig": false,
            "md5_digest": "41588b540b334bfb5af8bf979b30c28d",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7,<4.0",
            "size": 65710,
            "upload_time": "2024-01-29T21:54:40",
            "upload_time_iso_8601": "2024-01-29T21:54:40.155460Z",
            "url": "https://files.pythonhosted.org/packages/62/fb/0656025a3d203f3935a55aca0ad4385c51d4ec6df220059e5bd89e147193/ts2python-0.7.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-01-29 21:54:40",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "jecki",
    "github_project": "ts2python",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "ts2python"
}
        
Elapsed time: 0.18085s