qua-libs-core 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,28 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .eggs/
6
+
7
+ # Build artifacts
8
+ build/
9
+ dist/
10
+ *.whl
11
+ *.tar.gz
12
+
13
+ # Virtual environments / tooling
14
+ .venv/
15
+ .uv/
16
+ uv.lock.*
17
+ graphify-out/
18
+
19
+ # Test / type caches
20
+ .pytest_cache/
21
+ .mypy_cache/
22
+ .ruff_cache/
23
+
24
+ # Editor / OS
25
+ .idea/
26
+ .vscode/
27
+ .DS_Store
28
+ .cursor/
@@ -0,0 +1,37 @@
1
+
2
+ Quantum Machines End User License Agreement for qua-libs-core Software
3
+
4
+ PLEASE READ CAREFULLY THIS END USER LICENSE AGREEMENT (“EULA”) BEFORE INSTALLING, ACCESSING, DOWNLOADING OR OTHERWISE USING THE SOLUTION (AS DEFINED BELOW) (“USER”, “YOU”) BY QM (AS DEFINED BELOW). BY INSTALLING, HAVING INSTALLED, CONTROLLING, ACCESSING, OR OTHERWISE USING THE SOLUTION IN ANY MANNER, YOU ARE ACCEPTING AND AGREEING TO BE BOUND BY THIS EULA AND CONDITIONS HEREOF AND REPRESENTING THAT YOU HAVE FULL RIGHT, POWER, AND AUTHORITY TO ENTER INTO AND PERFORM HEREUNDER. YOU MAY NOT INSTALL, DEPLOY, CONTROL, ACCESS, OR USE THE SOLUTION IN ANY MANNER BEFORE YOU HAVE ACCEPTED THIS EULA. FURTHERMORE, YOU HEREBY WAIVE ANY RIGHTS OR REQUIREMENTS UNDER ANY LAWS OR REGULATIONS IN ANY JURISDICTION THAT REQUIRE AN ORIGINAL (NON-ELECTRONIC) SIGNATURE OR DELIVERY OR RETENTION OF NON-ELECTRONIC RECORDS, TO THE EXTENT PERMITTED UNDER APPLICABLE LAW. THIS EULA MADE BETWEEN YOU AND Q.M TECHNOLOGIES LTD. AND ITS AFFILIATES (AS DEFINED BELOW) (“QM”). WITH RESPECT TO THE SOLUTION YOU ASSUME ALL RESPONSIBILITY FOR THE SELECTION OF THE SOLUTION, FOR YOUR RELIANCE ON THE RESULTS OF THE USE OF THE SOLUTION AND RELATED SERVICES, AND FOR ANY USE OF THE SOLUTION NOT IN ACCORDANCE WITH THE EULA HEREOF OR AS CONTEMPLATED HEREUNDER.
5
+ THE PARTIES AGREE THAT UNLESS EXPRESSLY AND SPECIFICALLY AGREED TO IN WRITING BY QM , NO OTHER “CLICK THROGH”, “CLICK WRAP”, TERMS AND CONDITIONS OR OTHER STANDARD TERMS (INCLUDING WITHOUT LIMITATION CUSTOEMRS’ PURCHASE TERMS INCLUDING AS REFRESED IN A  QUOTE, OR ORDER), SHALL HAVE ANY FORCE OR EFFECT WITH RESPECT TO THE SOLUTION, THE USE THEREOF AND QM’S RIGHTS, RESPONSIBILITIES AND LIABILITIES, AND IN THE EVENT OF CONFLICT BETWEEN THIS EULA  AND THE PROVISIONS OF ANY SUCH OTHER INSTRUMNETS, THIS EULA SHALL PREVAIL.
6
+ 1. DEFINITIONS
7
+ 1.1 "Affiliate" means any entity which controls, is controlled, or is under common control with either of the parties. Any entity shall be deemed to "control" another entity if it owns directly or indirectly more than 50% of the outstanding voting securities or capital of another entity or other comparable equity with respect to an entity other than a company.
8
+ 1.2 "Documentation" means the standard written materials regarding the Solution issued and generally provided by QM to its customers.
9
+ 1.3 "Third Party Components" shall mean collectively any devices and products, whether hardware or software, which are (i) licensed by third parties and that are integrated into or with the Solution, or (ii) third-party equipment operated and/or used with the Solution, including any quantum computer equipment.
10
+ 1.4 "Software" shall mean QM’s proprietary software components, provided with and/or incorporated into the Solution.
11
+ 1.5 "Solution" shall mean QM’s proprietary dedicated Software, qua-libs-core, for designing, building, deploying, and running portable hybrid quantum-classical applications on top of QM’s proprietary products and services. The Solution specifically excludes QM proprietary products and any SW and HW in such products (or any other related products, either HW, or SW).
12
+ 2. LICENSE RIGHTS; RESTRICTIONS
13
+ 2.1 QM grants you, subject to full compliance with the EULA and conditions set forth, a non-exclusive, non-transferable, non-sublicensable, limited license to:
14
+ 2.1.1 use, access, and operate the Solution as provided, installed, and configured by QM, solely for your internal or personal use and solely with QM’s proprietary products previously purchased by you from QM and other Third Party Components, which specifically allowed to under the Documentation ("Purpose") and in any event not for any further commercialization or provision of the Solution or any parts thereof, to any third party or for the development of similar products, services, or solutions; and
15
+ 2.1.2 access, use, and make verbatim copies of the Documentation provided to you by QM, solely in connection with your internal or personal use of the Solution as permitted hereunder solely for the Purpose, and provided that all copyright notices are included and maintained therein.
16
+ 2.2 Use Restrictions.
17
+ 2.2.1 Unless otherwise expressly provided herein, you agree that you will not, nor will you allow any third party whether or not on your behalf to: (a) distribute, license, rent, lease, sublicense, loan, sell or otherwise allow any third party to access the Solution; (b) modify (except as specifically allowed by QM in the Documentation as part of your standard use of the Solution, and subject to Section 5 below), alter, copy, transfer, emulate or create any derivative works of the Solution or of any part thereof (including any of the Software components thereof); (c) reverse engineer, decompile, decode, decrypt, disassemble, or in any way attempt to derive source code or designs from the Solution or any part thereof (including of any of the Software components thereof); (d) remove, alter or obscure any copyright, trademark or other proprietary rights notice, on or in, the Solution, any of its components and/or the Documentation; (e) bundle, integrate, or attempt to integrate with the Solution or with any component thereof, any third-party software, hardware or technology other than as expressly permitted in writing by QM (including through the Documentation); (f) use the Solution for competing development activities, (g) publish or disclose to any third party any technical features, quality, performance or benchmark test, or comparative analyses relating to the Solution, except for your internal use or as expressly permitted by QM in writing; or (h) disable or otherwise circumvent any license management measures included in the Software and/or the Solution. You shall limit access to the Solution to your authorized employees, Affiliates, and personnel, and will administer account information and passwords accordingly, and will cause all such employees, Affiliates, and personnel to comply with the EULA of this EULA.
18
+ 2.2.2 Without derogating from the foregoing, you shall take all commercially reasonable precautions to prevent any unauthorized access and/or unauthorized usage of the Solution. You shall be responsible and liable for any act or omission by anyone acting on your (or your Affiliates’) behalf or authorization, and/or anyone having obtained use of or access to the Solution from you (or your Affiliates), including without limitation your employees, representatives, personnel, or your Affiliates, and such Affiliates’ employees, representatives, and personnel ("Representatives"), as if performed by you.
19
+ 2.3 Marks and Use of Name. This EULA does not grant you any rights to QM’s trademarks or service marks.
20
+ 2.4 Third Party Software. IN ACCEPTING THIS EULA, YOU CONFIRM AND ACKNOWLEDGE THE UTILIZATION OF THIRD-PARTY COMPONENTS, IN THE SOLUTION, OR THE USE OF THE SOLUTION WITH CERTAIN THIRD PARTY COMPONENTS ALLOWED TO UNDER THE DOCUMENTATION AND ACKNOWLEDGE THAT SUCH THIRD-PARTY COMPONENTS ARE BEING INSTALLED WITH YOUR CONSENT. THIRD PARTY COMPONENTS ARE UTILIZED ON AN "AS-IS" BASIS WITHOUT ANY WARRANTY WHATSOEVER AND QM HEREBY EXPRESSLY DISCLAIMS WITH RESPECT TO ANY SUCH THIRD PARTY COMPONENTS, AND TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW ALL WARRANTIES, WHETHER EXPRESS, IMPLIED, OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21
+ 2.5 Export Restrictions. You acknowledge that the Solution may be subject to applicable export jurisdiction and any other applicable laws and regulations concerning the transfer of the Solution or any part thereof across international borders. You will comply with all applicable national and international laws that apply to your use of the Solution, including the United States Export Administration Regulations, as well as end-user, end-use, and destination restrictions that may be issued by the United States and other governments from time to time.
22
+ 3. SUPPORT; DISCLAIMERS
23
+ 3.1 Alpha Version. You acknowledge that the Solution including all components thereof, is an Alpha/Beta version that is still under development, and as such (i) is not at the level of performance or compatibility of final, generally available products; (ii) may not operate correctly, (iii) may be further developed or modified; (iv) may not be made for general release, and (v) should not be used in a commercial production environment.
24
+ 3.2 THE SOLUTION, IS PROVIDED BY QM "AS-IS" AND QM MAKES NO REPRESENTATIONS OR WARRANTIES, ORAL OR WRITTEN, EXPRESS OR IMPLIED, REGARDING THE SOLUTION, ARISING FROM THE COURSE OF DEALING, COURSE OF PERFORMANCE, USAGE OF TRADE, QUALITY OF INFORMATION, QUIET ENJOYMENT OR OTHERWISE, INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, OR NON-INTERFERENCE. YOU ACKNOWLEDGE THAT YOU HAVE NOT ENTERED INTO THIS EULA IN RELIANCE UPON ANY WARRANTY OR REPRESENTATION NOT EXPRESSLY CONTAINED IN THIS EULA.
25
+ 4. FEES.
26
+ 4.1 If you are a paying customer, you shall pay QM the fees described in the Quote added with any applicable VAT or sales taxes (as applicable). Payment shall be due as described in the Quote and made in United States Dollars by wire transfer to QM’s designated bank account. All fees shall be non-cancellable, and the sums paid non-refundable. If you are a paying customer, you are responsible for payment of any taxes resulting from the possession and use of the Solution, except for payment of any taxes based on or related to QM’s income.
27
+ 5. PROPRIETARY RIGHTS.
28
+ 5.1 You agree and acknowledge that QM is and shall remain the sole and exclusive owner of any and all Intellectual Property rights in or to the Solution, including any Feedback provided by you or generated by QM, and any part thereof, including any modifications, enhancements, improvements, updates and upgrades, and derivative works thereof including if originates, learned or derived from the use of the Solution or any part thereof by you or by any Representatives or from the information you or any Representatives provide to QM in connection with the Solution.
29
+ 5.2 "Feedback" shall mean any feedback, including any code, documentation, or any original work of authorship, including any modifications or additions to an existing work, made by you as part of your use of the Solution.
30
+ 5.3 "Intellectual Property" shall mean all inventions, ideas, concepts, analyses, (whether patented, or patentable, or not), methods, methodologies, designs, processes, patents, patent applications, rights associated with works of authorship, including copyrights, copyrights applications, copyrights restrictions, moral rights, any information, ancillary materials, devices, results, know-how, and all rights relating to the protection of trade secrets and confidential information; design rights and industrial property rights; mask works, software, all code including source code, object code, firmware; and any other proprietary rights relating to intangible property. Other than as explicitly stated hereunder, no right or license, express or implied, in or to the Intellectual Property of QM, is granted to you or any Representative under this EULA.
31
+ 6. LIMITATION OF LIABILITY. IN NO EVENT WILL QM, ITS AFFILIATES, OR THEIR RESPECTIVE DIRECTORS, OFFICERS, SHAREHOLDER, AND EMPLOYEES’ ("QM’S PARTIES") AGGREGATE LIABILITY TO YOU, EXCEED THE AMOUNTS PAID BY YOU TO QM IN RESPECT OF THE SOLUTION. IN NO EVENT WILL QM OR QM PARTIES, HAVE ANY LIABILITY TO YOU FOR ANY INDIRECT, CONSEQUENTIAL, SPECIAL, EXEMPLARY, OR INCIDENTAL DAMAGES, INCLUDING WITHOUT LIMITATION DAMAGES FOR LOST PROFITS OR REVENUES, BUSINESS INTERRUPTION, LOSS OF GOODWILL, COMPUTER FAILURE OR MALFUNCTION, LOSS OF DATA OR BUSINESS INFORMATION ARISING FROM THE INSTALLATION, OPERATION, USE OF OR INABILITY TO USE THE SOLUTION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES OR IF SUCH POSSIBILITY WAS REASONABLY FORESEEABLE. NO ACTION, REGARDLESS OF FORM, ARISING OUT OF OR RELATING TO THIS EULA MAY BE BROUGHT AGAINST QM MORE THAN TWELVE (12) MONTHS AFTER THE TERMINATION OR EXPIRATION OF THIS EULA.
32
+ 7. TERM AND TERMINATION. You will have the rights set forth herein for the duration set forth by QM at its discretion (unless otherwise agreed between QM and you under an applicable written agreement) and only for so long as you comply with this EULA. This EULA and all rights and licenses granted hereunder shall automatically terminate if you breach the EULA hereof and such breach is not cured within fourteen (14) days of written notice of such breach. Sections 1, 2.2, 2.3, 2.4, 2.5, 5, 6, 7, and 8, will survive any termination or expiration of This EULA.
33
+ 8. GENERAL
34
+ 8.1 Severability. In the event any provision or part of This EULA is held to be invalid or unenforceable by any court of competent jurisdiction, it shall be amended to the extent required to render it valid, legal, and enforceable, or deleted if no such amendment is feasible, and such amendment or deletion shall not affect the enforceability of the other provisions hereof.
35
+ 8.2 Waiver. No waiver of any breach of This EULA will be a waiver of any other breach, and no waiver will be effective unless made in writing and signed by an authorized representative of the waiving party. The failure of either party to enforce any rights granted hereunder or to take action against the other party in the event of any breach hereunder shall not be deemed a waiver by that party as to subsequent enforcement of rights or subsequent actions in the event of future breaches.
36
+ 8.3 Entire Agreement; Updates. This EULA is in addition to QM’s Terms of Sale and End User License Agreement that related to QM’s proprietary products and services, including without limitation QM’s proprietary Quantum Orchestration™ Platform and applies only with respect to the subject matter hereof between you and QM – i.e., the use of the QM [QUAlibs] Software, any other EULA not specifically changed and/or modified by this EULA, shall be as set forth in QM’s Terms of Sale and End User License Agreement.
37
+ 8.4 Governing Law. The validity, interpretation, and performance of this EULA shall be controlled by and construed under the laws of the State of Israel as if performed wholly within Israel and without giving effect to the principles of conflicts of laws. The Parties hereby consent to the exclusive jurisdiction of the courts of Tel Aviv.
@@ -0,0 +1,132 @@
1
+ Metadata-Version: 2.4
2
+ Name: qua-libs-core
3
+ Version: 0.1.0
4
+ Summary: Generic QUA tutorials and shared libraries for modality-specific qua-libs repos
5
+ Project-URL: Homepage, https://github.com/qua-platform/qua-libs-core
6
+ Project-URL: Documentation, https://github.com/qua-platform/qua-libs-core/tree/main/docs
7
+ Project-URL: Repository, https://github.com/qua-platform/qua-libs-core
8
+ Project-URL: Issues, https://github.com/qua-platform/qua-libs-core/issues
9
+ Author-email: Quantum Machines <info@quantum-machines.co>
10
+ License:
11
+ Quantum Machines End User License Agreement for qua-libs-core Software
12
+
13
+ PLEASE READ CAREFULLY THIS END USER LICENSE AGREEMENT (“EULA”) BEFORE INSTALLING, ACCESSING, DOWNLOADING OR OTHERWISE USING THE SOLUTION (AS DEFINED BELOW) (“USER”, “YOU”) BY QM (AS DEFINED BELOW). BY INSTALLING, HAVING INSTALLED, CONTROLLING, ACCESSING, OR OTHERWISE USING THE SOLUTION IN ANY MANNER, YOU ARE ACCEPTING AND AGREEING TO BE BOUND BY THIS EULA AND CONDITIONS HEREOF AND REPRESENTING THAT YOU HAVE FULL RIGHT, POWER, AND AUTHORITY TO ENTER INTO AND PERFORM HEREUNDER. YOU MAY NOT INSTALL, DEPLOY, CONTROL, ACCESS, OR USE THE SOLUTION IN ANY MANNER BEFORE YOU HAVE ACCEPTED THIS EULA. FURTHERMORE, YOU HEREBY WAIVE ANY RIGHTS OR REQUIREMENTS UNDER ANY LAWS OR REGULATIONS IN ANY JURISDICTION THAT REQUIRE AN ORIGINAL (NON-ELECTRONIC) SIGNATURE OR DELIVERY OR RETENTION OF NON-ELECTRONIC RECORDS, TO THE EXTENT PERMITTED UNDER APPLICABLE LAW. THIS EULA MADE BETWEEN YOU AND Q.M TECHNOLOGIES LTD. AND ITS AFFILIATES (AS DEFINED BELOW) (“QM”). WITH RESPECT TO THE SOLUTION YOU ASSUME ALL RESPONSIBILITY FOR THE SELECTION OF THE SOLUTION, FOR YOUR RELIANCE ON THE RESULTS OF THE USE OF THE SOLUTION AND RELATED SERVICES, AND FOR ANY USE OF THE SOLUTION NOT IN ACCORDANCE WITH THE EULA HEREOF OR AS CONTEMPLATED HEREUNDER.
14
+ THE PARTIES AGREE THAT UNLESS EXPRESSLY AND SPECIFICALLY AGREED TO IN WRITING BY QM , NO OTHER “CLICK THROGH”, “CLICK WRAP”, TERMS AND CONDITIONS OR OTHER STANDARD TERMS (INCLUDING WITHOUT LIMITATION CUSTOEMRS’ PURCHASE TERMS INCLUDING AS REFRESED IN A  QUOTE, OR ORDER), SHALL HAVE ANY FORCE OR EFFECT WITH RESPECT TO THE SOLUTION, THE USE THEREOF AND QM’S RIGHTS, RESPONSIBILITIES AND LIABILITIES, AND IN THE EVENT OF CONFLICT BETWEEN THIS EULA  AND THE PROVISIONS OF ANY SUCH OTHER INSTRUMNETS, THIS EULA SHALL PREVAIL.
15
+ 1. DEFINITIONS
16
+ 1.1 "Affiliate" means any entity which controls, is controlled, or is under common control with either of the parties. Any entity shall be deemed to "control" another entity if it owns directly or indirectly more than 50% of the outstanding voting securities or capital of another entity or other comparable equity with respect to an entity other than a company.
17
+ 1.2 "Documentation" means the standard written materials regarding the Solution issued and generally provided by QM to its customers.
18
+ 1.3 "Third Party Components" shall mean collectively any devices and products, whether hardware or software, which are (i) licensed by third parties and that are integrated into or with the Solution, or (ii) third-party equipment operated and/or used with the Solution, including any quantum computer equipment.
19
+ 1.4 "Software" shall mean QM’s proprietary software components, provided with and/or incorporated into the Solution.
20
+ 1.5 "Solution" shall mean QM’s proprietary dedicated Software, qua-libs-core, for designing, building, deploying, and running portable hybrid quantum-classical applications on top of QM’s proprietary products and services. The Solution specifically excludes QM proprietary products and any SW and HW in such products (or any other related products, either HW, or SW).
21
+ 2. LICENSE RIGHTS; RESTRICTIONS
22
+ 2.1 QM grants you, subject to full compliance with the EULA and conditions set forth, a non-exclusive, non-transferable, non-sublicensable, limited license to:
23
+ 2.1.1 use, access, and operate the Solution as provided, installed, and configured by QM, solely for your internal or personal use and solely with QM’s proprietary products previously purchased by you from QM and other Third Party Components, which specifically allowed to under the Documentation ("Purpose") and in any event not for any further commercialization or provision of the Solution or any parts thereof, to any third party or for the development of similar products, services, or solutions; and
24
+ 2.1.2 access, use, and make verbatim copies of the Documentation provided to you by QM, solely in connection with your internal or personal use of the Solution as permitted hereunder solely for the Purpose, and provided that all copyright notices are included and maintained therein.
25
+ 2.2 Use Restrictions.
26
+ 2.2.1 Unless otherwise expressly provided herein, you agree that you will not, nor will you allow any third party whether or not on your behalf to: (a) distribute, license, rent, lease, sublicense, loan, sell or otherwise allow any third party to access the Solution; (b) modify (except as specifically allowed by QM in the Documentation as part of your standard use of the Solution, and subject to Section 5 below), alter, copy, transfer, emulate or create any derivative works of the Solution or of any part thereof (including any of the Software components thereof); (c) reverse engineer, decompile, decode, decrypt, disassemble, or in any way attempt to derive source code or designs from the Solution or any part thereof (including of any of the Software components thereof); (d) remove, alter or obscure any copyright, trademark or other proprietary rights notice, on or in, the Solution, any of its components and/or the Documentation; (e) bundle, integrate, or attempt to integrate with the Solution or with any component thereof, any third-party software, hardware or technology other than as expressly permitted in writing by QM (including through the Documentation); (f) use the Solution for competing development activities, (g) publish or disclose to any third party any technical features, quality, performance or benchmark test, or comparative analyses relating to the Solution, except for your internal use or as expressly permitted by QM in writing; or (h) disable or otherwise circumvent any license management measures included in the Software and/or the Solution. You shall limit access to the Solution to your authorized employees, Affiliates, and personnel, and will administer account information and passwords accordingly, and will cause all such employees, Affiliates, and personnel to comply with the EULA of this EULA.
27
+ 2.2.2 Without derogating from the foregoing, you shall take all commercially reasonable precautions to prevent any unauthorized access and/or unauthorized usage of the Solution. You shall be responsible and liable for any act or omission by anyone acting on your (or your Affiliates’) behalf or authorization, and/or anyone having obtained use of or access to the Solution from you (or your Affiliates), including without limitation your employees, representatives, personnel, or your Affiliates, and such Affiliates’ employees, representatives, and personnel ("Representatives"), as if performed by you.
28
+ 2.3 Marks and Use of Name. This EULA does not grant you any rights to QM’s trademarks or service marks.
29
+ 2.4 Third Party Software. IN ACCEPTING THIS EULA, YOU CONFIRM AND ACKNOWLEDGE THE UTILIZATION OF THIRD-PARTY COMPONENTS, IN THE SOLUTION, OR THE USE OF THE SOLUTION WITH CERTAIN THIRD PARTY COMPONENTS ALLOWED TO UNDER THE DOCUMENTATION AND ACKNOWLEDGE THAT SUCH THIRD-PARTY COMPONENTS ARE BEING INSTALLED WITH YOUR CONSENT. THIRD PARTY COMPONENTS ARE UTILIZED ON AN "AS-IS" BASIS WITHOUT ANY WARRANTY WHATSOEVER AND QM HEREBY EXPRESSLY DISCLAIMS WITH RESPECT TO ANY SUCH THIRD PARTY COMPONENTS, AND TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW ALL WARRANTIES, WHETHER EXPRESS, IMPLIED, OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30
+ 2.5 Export Restrictions. You acknowledge that the Solution may be subject to applicable export jurisdiction and any other applicable laws and regulations concerning the transfer of the Solution or any part thereof across international borders. You will comply with all applicable national and international laws that apply to your use of the Solution, including the United States Export Administration Regulations, as well as end-user, end-use, and destination restrictions that may be issued by the United States and other governments from time to time.
31
+ 3. SUPPORT; DISCLAIMERS
32
+ 3.1 Alpha Version. You acknowledge that the Solution including all components thereof, is an Alpha/Beta version that is still under development, and as such (i) is not at the level of performance or compatibility of final, generally available products; (ii) may not operate correctly, (iii) may be further developed or modified; (iv) may not be made for general release, and (v) should not be used in a commercial production environment.
33
+ 3.2 THE SOLUTION, IS PROVIDED BY QM "AS-IS" AND QM MAKES NO REPRESENTATIONS OR WARRANTIES, ORAL OR WRITTEN, EXPRESS OR IMPLIED, REGARDING THE SOLUTION, ARISING FROM THE COURSE OF DEALING, COURSE OF PERFORMANCE, USAGE OF TRADE, QUALITY OF INFORMATION, QUIET ENJOYMENT OR OTHERWISE, INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, OR NON-INTERFERENCE. YOU ACKNOWLEDGE THAT YOU HAVE NOT ENTERED INTO THIS EULA IN RELIANCE UPON ANY WARRANTY OR REPRESENTATION NOT EXPRESSLY CONTAINED IN THIS EULA.
34
+ 4. FEES.
35
+ 4.1 If you are a paying customer, you shall pay QM the fees described in the Quote added with any applicable VAT or sales taxes (as applicable). Payment shall be due as described in the Quote and made in United States Dollars by wire transfer to QM’s designated bank account. All fees shall be non-cancellable, and the sums paid non-refundable. If you are a paying customer, you are responsible for payment of any taxes resulting from the possession and use of the Solution, except for payment of any taxes based on or related to QM’s income.
36
+ 5. PROPRIETARY RIGHTS.
37
+ 5.1 You agree and acknowledge that QM is and shall remain the sole and exclusive owner of any and all Intellectual Property rights in or to the Solution, including any Feedback provided by you or generated by QM, and any part thereof, including any modifications, enhancements, improvements, updates and upgrades, and derivative works thereof including if originates, learned or derived from the use of the Solution or any part thereof by you or by any Representatives or from the information you or any Representatives provide to QM in connection with the Solution.
38
+ 5.2 "Feedback" shall mean any feedback, including any code, documentation, or any original work of authorship, including any modifications or additions to an existing work, made by you as part of your use of the Solution.
39
+ 5.3 "Intellectual Property" shall mean all inventions, ideas, concepts, analyses, (whether patented, or patentable, or not), methods, methodologies, designs, processes, patents, patent applications, rights associated with works of authorship, including copyrights, copyrights applications, copyrights restrictions, moral rights, any information, ancillary materials, devices, results, know-how, and all rights relating to the protection of trade secrets and confidential information; design rights and industrial property rights; mask works, software, all code including source code, object code, firmware; and any other proprietary rights relating to intangible property. Other than as explicitly stated hereunder, no right or license, express or implied, in or to the Intellectual Property of QM, is granted to you or any Representative under this EULA.
40
+ 6. LIMITATION OF LIABILITY. IN NO EVENT WILL QM, ITS AFFILIATES, OR THEIR RESPECTIVE DIRECTORS, OFFICERS, SHAREHOLDER, AND EMPLOYEES’ ("QM’S PARTIES") AGGREGATE LIABILITY TO YOU, EXCEED THE AMOUNTS PAID BY YOU TO QM IN RESPECT OF THE SOLUTION. IN NO EVENT WILL QM OR QM PARTIES, HAVE ANY LIABILITY TO YOU FOR ANY INDIRECT, CONSEQUENTIAL, SPECIAL, EXEMPLARY, OR INCIDENTAL DAMAGES, INCLUDING WITHOUT LIMITATION DAMAGES FOR LOST PROFITS OR REVENUES, BUSINESS INTERRUPTION, LOSS OF GOODWILL, COMPUTER FAILURE OR MALFUNCTION, LOSS OF DATA OR BUSINESS INFORMATION ARISING FROM THE INSTALLATION, OPERATION, USE OF OR INABILITY TO USE THE SOLUTION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES OR IF SUCH POSSIBILITY WAS REASONABLY FORESEEABLE. NO ACTION, REGARDLESS OF FORM, ARISING OUT OF OR RELATING TO THIS EULA MAY BE BROUGHT AGAINST QM MORE THAN TWELVE (12) MONTHS AFTER THE TERMINATION OR EXPIRATION OF THIS EULA.
41
+ 7. TERM AND TERMINATION. You will have the rights set forth herein for the duration set forth by QM at its discretion (unless otherwise agreed between QM and you under an applicable written agreement) and only for so long as you comply with this EULA. This EULA and all rights and licenses granted hereunder shall automatically terminate if you breach the EULA hereof and such breach is not cured within fourteen (14) days of written notice of such breach. Sections 1, 2.2, 2.3, 2.4, 2.5, 5, 6, 7, and 8, will survive any termination or expiration of This EULA.
42
+ 8. GENERAL
43
+ 8.1 Severability. In the event any provision or part of This EULA is held to be invalid or unenforceable by any court of competent jurisdiction, it shall be amended to the extent required to render it valid, legal, and enforceable, or deleted if no such amendment is feasible, and such amendment or deletion shall not affect the enforceability of the other provisions hereof.
44
+ 8.2 Waiver. No waiver of any breach of This EULA will be a waiver of any other breach, and no waiver will be effective unless made in writing and signed by an authorized representative of the waiving party. The failure of either party to enforce any rights granted hereunder or to take action against the other party in the event of any breach hereunder shall not be deemed a waiver by that party as to subsequent enforcement of rights or subsequent actions in the event of future breaches.
45
+ 8.3 Entire Agreement; Updates. This EULA is in addition to QM’s Terms of Sale and End User License Agreement that related to QM’s proprietary products and services, including without limitation QM’s proprietary Quantum Orchestration™ Platform and applies only with respect to the subject matter hereof between you and QM – i.e., the use of the QM [QUAlibs] Software, any other EULA not specifically changed and/or modified by this EULA, shall be as set forth in QM’s Terms of Sale and End User License Agreement.
46
+ 8.4 Governing Law. The validity, interpretation, and performance of this EULA shall be controlled by and construed under the laws of the State of Israel as if performed wholly within Israel and without giving effect to the principles of conflicts of laws. The Parties hereby consent to the exclusive jurisdiction of the courts of Tel Aviv.
47
+ License-File: LICENSE
48
+ Classifier: License :: Other/Proprietary License
49
+ Classifier: Operating System :: OS Independent
50
+ Classifier: Programming Language :: Python :: 3
51
+ Requires-Python: <3.13,>=3.10
52
+ Requires-Dist: opentelemetry-api>=1.20.0
53
+ Requires-Dist: opentelemetry-exporter-otlp>=1.20.0
54
+ Requires-Dist: opentelemetry-sdk>=1.20.0
55
+ Requires-Dist: tomli>=2.0.1; python_version < '3.11'
56
+ Requires-Dist: uptrace>=1.20.0
57
+ Provides-Extra: tutorials
58
+ Requires-Dist: matplotlib>=3.2.2; extra == 'tutorials'
59
+ Requires-Dist: numpy>=1.18.5; extra == 'tutorials'
60
+ Requires-Dist: plotly>=5.24.1; extra == 'tutorials'
61
+ Requires-Dist: qm-qua>=1.2.0; extra == 'tutorials'
62
+ Requires-Dist: qm-saas; extra == 'tutorials'
63
+ Requires-Dist: qualang-tools>=0.19.0; extra == 'tutorials'
64
+ Requires-Dist: scipy>=1.7.0; extra == 'tutorials'
65
+ Description-Content-Type: text/markdown
66
+
67
+ ![Banner](GITHUB-BANNER.jpg)
68
+
69
+ [![discord](https://img.shields.io/discord/806244683403100171?label=QUA&logo=Discord&style=plastic)](https://discord.gg/7FfhhpswbP)
70
+ [![License](https://img.shields.io/badge/license-Proprietary-blue.svg)](./LICENSE)
71
+
72
+ <!-- Netlify (docs deploy) and Zenodo (citable DOI) badges are placeholders;
73
+ fill in the IDs once this repo has its own Netlify site and Zenodo record. -->
74
+ [![Netlify Status](https://api.netlify.com/api/v1/badges/REPLACE_WITH_NETLIFY_SITE_ID/deploy-status)](https://app.netlify.com/sites/qua-libs-core/deploys)
75
+ [![DOI](https://zenodo.org/badge/REPLACE_WITH_ZENODO_ID.svg)](https://zenodo.org/badge/latestdoi/REPLACE_WITH_ZENODO_ID)
76
+
77
+ # QUA Libraries
78
+
79
+ Hey! Glad to see you there!
80
+
81
+ Welcome to the QUA libraries. Your one-stop-shop for a batteries-included QUA experience.
82
+
83
+ This repo is where we share the general-purpose tutorials and tools that aren't tied to any particular qubit platform, and it points you to the platform-specific libraries below.
84
+
85
+ It includes:
86
+ * The ["Tutorials"](./Tutorials) folder contains various tutorials and guides for working with the OPX — timing, streams, demodulation, simulation, macros, Octave, and more.
87
+
88
+ ## Installing
89
+
90
+ Install `qua-libs-core` from PyPI:
91
+
92
+ ```bash
93
+ pip install qua-libs-core
94
+ ```
95
+ That gives you the importable `qua_libs_core` package, including `qua_libs_core.telemetry` used across the qua-libs repositories, without the QUA SDK.
96
+
97
+ Or clone this repository for tutorials and the installer in addition to telemetry:
98
+
99
+ ```bash
100
+ git clone https://github.com/qua-platform/qua-libs-core
101
+ cd qua-libs-core
102
+ uv sync --extra tutorials
103
+ ```
104
+
105
+ Documentation for telemetry is seen in
106
+ [`qua_libs_core.telemetry`](docs/telemetry/README.md).
107
+
108
+ ### QUA Libraries installer
109
+
110
+ For a batteries-included modality setup (clone, virtualenv, QUAlibrate, optional
111
+ local Uptrace), use [`tools/installer/`](tools/installer/README.md).
112
+ See [telemetry installer docs](docs/telemetry/INSTALLER.md) for Docker and config
113
+ file behavior.
114
+
115
+ ## QUA libraries by platform
116
+
117
+ Examples, use cases, and calibration protocols for specific qubit platforms live in their own repositories:
118
+
119
+ | Repository | Platform |
120
+ |---|---|
121
+ | [qua-libs-superconducting](https://github.com/qua-platform/qua-libs-superconducting) | Superconducting transmons |
122
+ | [qua-libs-nv](https://github.com/qua-platform/qua-libs-nv) | NV / optically addressable spin qubits |
123
+ | [qua-libs-quantum-dots](https://github.com/qua-platform/qua-libs-quantum-dots) | Quantum dots |
124
+ | [qua-libs-neutral-atoms](https://github.com/qua-platform/qua-libs-neutral-atoms) | Neutral atoms (Rydberg, cavity locking) |
125
+ | [qua-libs-trapped-ion](https://github.com/qua-platform/qua-libs-trapped-ion) | Trapped ions |
126
+
127
+ ## Support and Contribution
128
+ This is a beta version of the repo, and thus, if you see quirks and inaccuracies please tell us!
129
+ Love to see some example that's not yet included? tell us! Have a request for a general purpose procedure? tell us!
130
+ Already have something cool that others could use? Open a pull request! You can follow [this guide](./CONTRIBUTING.md) and feel free to contact us if you need any help.
131
+ Issue reporting and requests should be done via the [GitHub issues system](https://github.com/qua-platform/qua-libs-core/issues), that should give a transparent experience where all users can see what's coming and which issues are already known.
132
+ We hope this repo becomes a useful resource, giving real contribution to the community, and we'd love to see your ideas and contributions too!
@@ -0,0 +1,66 @@
1
+ ![Banner](GITHUB-BANNER.jpg)
2
+
3
+ [![discord](https://img.shields.io/discord/806244683403100171?label=QUA&logo=Discord&style=plastic)](https://discord.gg/7FfhhpswbP)
4
+ [![License](https://img.shields.io/badge/license-Proprietary-blue.svg)](./LICENSE)
5
+
6
+ <!-- Netlify (docs deploy) and Zenodo (citable DOI) badges are placeholders;
7
+ fill in the IDs once this repo has its own Netlify site and Zenodo record. -->
8
+ [![Netlify Status](https://api.netlify.com/api/v1/badges/REPLACE_WITH_NETLIFY_SITE_ID/deploy-status)](https://app.netlify.com/sites/qua-libs-core/deploys)
9
+ [![DOI](https://zenodo.org/badge/REPLACE_WITH_ZENODO_ID.svg)](https://zenodo.org/badge/latestdoi/REPLACE_WITH_ZENODO_ID)
10
+
11
+ # QUA Libraries
12
+
13
+ Hey! Glad to see you there!
14
+
15
+ Welcome to the QUA libraries. Your one-stop-shop for a batteries-included QUA experience.
16
+
17
+ This repo is where we share the general-purpose tutorials and tools that aren't tied to any particular qubit platform, and it points you to the platform-specific libraries below.
18
+
19
+ It includes:
20
+ * The ["Tutorials"](./Tutorials) folder contains various tutorials and guides for working with the OPX — timing, streams, demodulation, simulation, macros, Octave, and more.
21
+
22
+ ## Installing
23
+
24
+ Install `qua-libs-core` from PyPI:
25
+
26
+ ```bash
27
+ pip install qua-libs-core
28
+ ```
29
+ That gives you the importable `qua_libs_core` package, including `qua_libs_core.telemetry` used across the qua-libs repositories, without the QUA SDK.
30
+
31
+ Or clone this repository for tutorials and the installer in addition to telemetry:
32
+
33
+ ```bash
34
+ git clone https://github.com/qua-platform/qua-libs-core
35
+ cd qua-libs-core
36
+ uv sync --extra tutorials
37
+ ```
38
+
39
+ Documentation for telemetry is seen in
40
+ [`qua_libs_core.telemetry`](docs/telemetry/README.md).
41
+
42
+ ### QUA Libraries installer
43
+
44
+ For a batteries-included modality setup (clone, virtualenv, QUAlibrate, optional
45
+ local Uptrace), use [`tools/installer/`](tools/installer/README.md).
46
+ See [telemetry installer docs](docs/telemetry/INSTALLER.md) for Docker and config
47
+ file behavior.
48
+
49
+ ## QUA libraries by platform
50
+
51
+ Examples, use cases, and calibration protocols for specific qubit platforms live in their own repositories:
52
+
53
+ | Repository | Platform |
54
+ |---|---|
55
+ | [qua-libs-superconducting](https://github.com/qua-platform/qua-libs-superconducting) | Superconducting transmons |
56
+ | [qua-libs-nv](https://github.com/qua-platform/qua-libs-nv) | NV / optically addressable spin qubits |
57
+ | [qua-libs-quantum-dots](https://github.com/qua-platform/qua-libs-quantum-dots) | Quantum dots |
58
+ | [qua-libs-neutral-atoms](https://github.com/qua-platform/qua-libs-neutral-atoms) | Neutral atoms (Rydberg, cavity locking) |
59
+ | [qua-libs-trapped-ion](https://github.com/qua-platform/qua-libs-trapped-ion) | Trapped ions |
60
+
61
+ ## Support and Contribution
62
+ This is a beta version of the repo, and thus, if you see quirks and inaccuracies please tell us!
63
+ Love to see some example that's not yet included? tell us! Have a request for a general purpose procedure? tell us!
64
+ Already have something cool that others could use? Open a pull request! You can follow [this guide](./CONTRIBUTING.md) and feel free to contact us if you need any help.
65
+ Issue reporting and requests should be done via the [GitHub issues system](https://github.com/qua-platform/qua-libs-core/issues), that should give a transparent experience where all users can see what's coming and which issues are already known.
66
+ We hope this repo becomes a useful resource, giving real contribution to the community, and we'd love to see your ideas and contributions too!
@@ -0,0 +1,71 @@
1
+ # qua-libs-core: generic QUA tutorials, shared tooling, and the `qua_libs_core`
2
+ # package (including `qua_libs_core.telemetry` for modality repositories).
3
+
4
+ [project]
5
+ name = "qua-libs-core"
6
+ dynamic = ["version"]
7
+ description = "Generic QUA tutorials and shared libraries for modality-specific qua-libs repos"
8
+ readme = "README.md"
9
+ license = { file = "LICENSE" }
10
+ authors = [{ name = "Quantum Machines", email = "info@quantum-machines.co" }]
11
+ requires-python = ">=3.10,<3.13"
12
+ classifiers = [
13
+ "License :: Other/Proprietary License",
14
+ "Programming Language :: Python :: 3",
15
+ "Operating System :: OS Independent",
16
+ ]
17
+ dependencies = [
18
+ "uptrace>=1.20.0",
19
+ "opentelemetry-api>=1.20.0",
20
+ "opentelemetry-sdk>=1.20.0",
21
+ "opentelemetry-exporter-otlp>=1.20.0",
22
+ "tomli>=2.0.1; python_version < '3.11'",
23
+ ]
24
+
25
+ [project.optional-dependencies]
26
+ tutorials = [
27
+ "qm-qua>=1.2.0",
28
+ "qualang-tools>=0.19.0",
29
+ "qm-saas",
30
+ "numpy>=1.18.5",
31
+ "scipy>=1.7.0",
32
+ "matplotlib>=3.2.2",
33
+ "plotly>=5.24.1",
34
+ ]
35
+
36
+ [project.urls]
37
+ Homepage = "https://github.com/qua-platform/qua-libs-core"
38
+ Documentation = "https://github.com/qua-platform/qua-libs-core/tree/main/docs"
39
+ Repository = "https://github.com/qua-platform/qua-libs-core"
40
+ Issues = "https://github.com/qua-platform/qua-libs-core/issues"
41
+
42
+ [build-system]
43
+ requires = ["hatchling"]
44
+ build-backend = "hatchling.build"
45
+
46
+ [tool.hatch.version]
47
+ path = "qua_libs_core/__init__.py"
48
+
49
+ [tool.hatch.build.targets.sdist]
50
+ only-include = ["qua_libs_core"]
51
+
52
+ [tool.hatch.build.targets.wheel]
53
+ packages = ["qua_libs_core"]
54
+
55
+ [dependency-groups]
56
+ dev = ["black>=24.3,<25", "ruff>=0.6,<1", "pytest>=8.0", "pre-commit>=4.0"]
57
+
58
+ [tool.pytest.ini_options]
59
+ testpaths = ["tests"]
60
+
61
+ [tool.black]
62
+ line-length = 120
63
+
64
+ [tool.ruff]
65
+ line-length = 120
66
+
67
+ [tool.ruff.lint]
68
+ # `from qm.qua import *` is the idiomatic QUA style (F403/F405); single-letter
69
+ # names like I/Q/l are standard in physics code (E741). Ignoring these keeps
70
+ # ruff's output useful. Run locally with: uv run ruff check .
71
+ ignore = ["F403", "F405", "E741"]
@@ -0,0 +1,10 @@
1
+ """qua-libs-core importable package.
2
+
3
+ Currently ships the shared ``telemetry`` subpackage — OpenTelemetry + Uptrace
4
+ instrumentation used by the per-modality qua-libs repos. Telemetry is off by
5
+ default; see ``docs/telemetry/`` for usage. Import as::
6
+
7
+ from qua_libs_core.telemetry import instrument_calibration_node
8
+ """
9
+
10
+ __version__ = "0.1.0"
@@ -0,0 +1,50 @@
1
+ """
2
+ Telemetry module for OpenTelemetry + Uptrace integration.
3
+
4
+ Example usage:
5
+ from qua_libs_core.telemetry import init_telemetry, trace_function, trace_span
6
+
7
+ # Initialize once at application startup (reads .qua-libs/telemetry.toml)
8
+ init_telemetry()
9
+
10
+ # Option 1: Use decorator for automatic instrumentation
11
+ @trace_function("my_function")
12
+ def my_function():
13
+ ...
14
+
15
+ # Option 2: Use context manager for manual spans
16
+ with trace_span("my_operation"):
17
+ ...
18
+ """
19
+
20
+ from .config import TelemetryConfig, init_telemetry, get_tracer
21
+ from .decorators import trace_function, trace_async_function
22
+ from .context_managers import trace_span, trace_span_with_attributes
23
+ from .utils import (
24
+ set_span_attribute,
25
+ add_span_event,
26
+ record_exception,
27
+ set_span_status,
28
+ get_current_span,
29
+ )
30
+ from .calibration_node import instrument_calibration_node
31
+ from .project_config import PROJECT_CONFIG, load_project_config
32
+
33
+
34
+ __all__ = [
35
+ "TelemetryConfig",
36
+ "init_telemetry",
37
+ "get_tracer",
38
+ "trace_function",
39
+ "trace_async_function",
40
+ "trace_span",
41
+ "trace_span_with_attributes",
42
+ "set_span_attribute",
43
+ "add_span_event",
44
+ "record_exception",
45
+ "set_span_status",
46
+ "get_current_span",
47
+ "instrument_calibration_node",
48
+ "PROJECT_CONFIG",
49
+ "load_project_config",
50
+ ]
@@ -0,0 +1,157 @@
1
+ """
2
+ Centralized telemetry instrumentation for calibration nodes.
3
+
4
+ Usage:
5
+ from qua_libs_core.telemetry import instrument_calibration_node
6
+
7
+ node = QualibrationNode[Parameters, Quam](name="my_node", ...)
8
+ instrument_calibration_node(node) # call once, before any @node.run_action defs
9
+
10
+ @node.run_action(skip_if=...)
11
+ def create_qua_program(node):
12
+ ... # unchanged — telemetry is added automatically
13
+ """
14
+
15
+ import functools
16
+ from datetime import datetime
17
+ from typing import Any, Dict, List, Optional
18
+
19
+ import uptrace
20
+ from opentelemetry.trace import Status, StatusCode
21
+
22
+ from .config import init_telemetry, TelemetryConfig, get_tracer
23
+ from .project_config import load_project_config
24
+
25
+
26
+ STANDARD_FUNCTIONS = [
27
+ "custom_param",
28
+ "create_qua_program",
29
+ "simulate_qua_program",
30
+ "execute_qua_program",
31
+ "load_data",
32
+ "analyse_data",
33
+ "plot_data",
34
+ "update_state",
35
+ "save_results",
36
+ ]
37
+
38
+ # Parameter attributes to capture from node.parameters when available
39
+ _OPTIONAL_ATTRS = ["operation", "num_shots", "timeout", "load_data_id"]
40
+
41
+
42
+ def instrument_calibration_node(
43
+ node,
44
+ config: Optional[TelemetryConfig] = None,
45
+ extra_attributes: Optional[List[str]] = None,
46
+ resource_attributes: Optional[Dict[str, Any]] = None,
47
+ ) -> None:
48
+ """
49
+ Instrument a calibration node's standard run_action functions with telemetry spans.
50
+
51
+ Patches node.run_action so every function listed in STANDARD_FUNCTIONS that is
52
+ subsequently decorated with @node.run_action gets automatically wrapped in a
53
+ trace span. Functions not in STANDARD_FUNCTIONS are passed through unchanged.
54
+
55
+ Call this ONCE, immediately after node creation and BEFORE any @node.run_action
56
+ function definitions.
57
+
58
+ Args:
59
+ node: A QualibrationNode instance.
60
+ config: Optional TelemetryConfig. If None, reloads ``.qua-libs/telemetry.toml``
61
+ from the current working directory (and parents).
62
+ extra_attributes: Optional list of additional parameter names to capture
63
+ from node.parameters as span attributes (extends the default set of
64
+ operation, num_shots, timeout, load_data_id).
65
+ resource_attributes: Optional dict of resource-level attributes passed to
66
+ Uptrace (e.g., experiment.category, experiment.run_at). Only takes
67
+ effect on the first init_telemetry call per process.
68
+
69
+ Advanced usage — accessing the span inside a function:
70
+ from qua_libs_core.telemetry import get_current_span, set_span_attribute
71
+
72
+ @node.run_action(skip_if=node.parameters.simulate)
73
+ def analyse_data(node):
74
+ span = get_current_span()
75
+ set_span_attribute(span, "fit.q1", "successful")
76
+
77
+ The span is also available via node.namespace["_telemetry_span"].
78
+ """
79
+ if config is None:
80
+ config = load_project_config()
81
+
82
+ # Auto-populate resource attributes from node name and current time
83
+ auto_attrs = {
84
+ "experiment.node": node.name,
85
+ "experiment.run_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
86
+ }
87
+ # User-provided resource_attributes override auto ones
88
+ merged_attrs = {
89
+ **auto_attrs,
90
+ **(config.resource_attributes or {}),
91
+ **(resource_attributes or {}),
92
+ }
93
+
94
+ if merged_attrs != (config.resource_attributes or {}):
95
+ config = TelemetryConfig(
96
+ dsn=config.dsn,
97
+ service_name=config.service_name,
98
+ service_version=config.service_version,
99
+ deployment_environment=config.deployment_environment,
100
+ enabled=config.enabled,
101
+ resource_attributes=merged_attrs,
102
+ )
103
+
104
+ init_telemetry(config)
105
+
106
+ node_name = node.name
107
+ original_run_action = node.run_action
108
+
109
+ param_attributes = list(_OPTIONAL_ATTRS)
110
+ if extra_attributes:
111
+ param_attributes.extend(extra_attributes)
112
+
113
+ def traced_run_action(*args, **kwargs):
114
+ decorator = original_run_action(*args, **kwargs)
115
+
116
+ def wrapping_decorator(fn):
117
+ if fn.__name__ not in STANDARD_FUNCTIONS:
118
+ return decorator(fn)
119
+
120
+ @functools.wraps(fn)
121
+ def traced_fn(*fn_args, **fn_kwargs):
122
+ tracer = get_tracer()
123
+ attrs = {"node": node_name}
124
+
125
+ # Collect optional span attributes from node.parameters
126
+ if fn_args:
127
+ params = getattr(fn_args[0], "parameters", None)
128
+ if params is not None:
129
+ for attr in param_attributes:
130
+ val = getattr(params, attr, None)
131
+ if val is not None:
132
+ attrs[attr] = str(val)
133
+
134
+ with tracer.start_as_current_span(f"{node_name}.{fn.__name__}") as span:
135
+ for key, value in attrs.items():
136
+ span.set_attribute(key, value)
137
+ node.namespace["_telemetry_span"] = span
138
+ try:
139
+ result = fn(*fn_args, **fn_kwargs)
140
+ if fn.__name__ == "save_results":
141
+ try:
142
+ uptrace.force_flush()
143
+ except Exception:
144
+ pass
145
+ return result
146
+ except Exception as e:
147
+ span.record_exception(e)
148
+ span.set_status(Status(StatusCode.ERROR, str(e)))
149
+ raise
150
+ finally:
151
+ node.namespace.pop("_telemetry_span", None)
152
+
153
+ return decorator(traced_fn)
154
+
155
+ return wrapping_decorator
156
+
157
+ node.run_action = traced_run_action
@@ -0,0 +1,138 @@
1
+ """
2
+ Telemetry configuration and initialization module.
3
+ """
4
+
5
+ import logging
6
+ import os
7
+ from typing import Optional, Dict, Any
8
+ from opentelemetry import trace
9
+ import uptrace
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+ # pylint: disable=too-many-arguments,too-many-positional-arguments,too-few-public-methods
14
+
15
+
16
+ class TelemetryConfig:
17
+ """Configuration class for telemetry settings."""
18
+
19
+ def __init__(
20
+ self,
21
+ dsn: Optional[str] = None,
22
+ service_name: Optional[str] = None,
23
+ service_version: Optional[str] = None,
24
+ deployment_environment: Optional[str] = None,
25
+ enabled: Optional[bool] = None,
26
+ resource_attributes: Optional[Dict[str, Any]] = None,
27
+ ):
28
+ """
29
+ Initialize telemetry configuration.
30
+
31
+ Args:
32
+ dsn: Uptrace DSN (defaults to UPTRACE_DSN env var)
33
+ service_name: Service name (defaults to UPTRACE_SERVICE_NAME env var or "qua-libs")
34
+ service_version: Service version (defaults to UPTRACE_SERVICE_VERSION env var or "1.0.0")
35
+ deployment_environment: Deployment environment (defaults to UPTRACE_ENV env var or "production")
36
+ enabled: Whether telemetry is enabled (defaults to UPTRACE_ENABLED env var or False)
37
+ resource_attributes: Extra key-value metadata attached to every span automatically
38
+ """
39
+ self.dsn = dsn or os.getenv("UPTRACE_DSN")
40
+ self.resource_attributes = resource_attributes or {}
41
+ self.service_name = service_name or os.getenv("UPTRACE_SERVICE_NAME", "qua-libs")
42
+ self.service_version = service_version or os.getenv("UPTRACE_SERVICE_VERSION", "1.0.0")
43
+ self.deployment_environment = deployment_environment or os.getenv("UPTRACE_ENV", "production")
44
+
45
+ # Off by default. Enable via .qua-libs/telemetry.toml, UPTRACE_ENABLED=true, or enabled=True.
46
+ enabled_str = os.getenv("UPTRACE_ENABLED", "false").lower()
47
+ self.enabled = enabled if enabled is not None else (enabled_str in ("true", "1", "yes"))
48
+
49
+ # Note: Enabled-but-no-DSN is handled in init_telemetry; do not raise in __init__.
50
+
51
+
52
+ # Global state
53
+ _telemetry_initialized = False
54
+ _tracer = None
55
+
56
+
57
+ def init_telemetry(config: Optional[TelemetryConfig] = None) -> None:
58
+ """
59
+ Initialize OpenTelemetry with Uptrace.
60
+
61
+ This should be called once at application startup.
62
+ Subsequent calls are safe and will be ignored.
63
+
64
+ Args:
65
+ config: TelemetryConfig instance. If None, loads from .qua-libs/telemetry.toml,
66
+ environment variables, and built-in defaults via load_project_config().
67
+ """
68
+ global _telemetry_initialized, _tracer
69
+
70
+ if _telemetry_initialized:
71
+ return
72
+
73
+ if config is None:
74
+ from .project_config import load_project_config
75
+
76
+ config = load_project_config()
77
+
78
+ if not config.enabled:
79
+ logger.info(
80
+ "Telemetry is disabled (off by default). "
81
+ "Set enabled=true in .qua-libs/telemetry.toml, UPTRACE_ENABLED=true, "
82
+ "or pass TelemetryConfig(enabled=True, dsn=...) to enable."
83
+ )
84
+ _telemetry_initialized = True
85
+ return
86
+
87
+ if not config.dsn:
88
+ # Enabled but no destination configured. Stay disabled rather than crash —
89
+ # telemetry must never break a calibration run.
90
+ logger.warning(
91
+ "Telemetry is enabled but no Uptrace DSN was provided. "
92
+ "Set UPTRACE_DSN (or pass dsn=...). Telemetry stays disabled."
93
+ )
94
+ _telemetry_initialized = True
95
+ return
96
+
97
+ try:
98
+ uptrace.configure_opentelemetry(
99
+ dsn=config.dsn,
100
+ service_name=config.service_name,
101
+ service_version=config.service_version,
102
+ deployment_environment=config.deployment_environment,
103
+ resource_attributes=config.resource_attributes,
104
+ )
105
+ _tracer = trace.get_tracer(config.service_name, config.service_version)
106
+ _telemetry_initialized = True
107
+ logger.info("Telemetry initialized: %s v%s", config.service_name, config.service_version)
108
+ except Exception as e:
109
+ logger.warning("Failed to initialize telemetry: %s", e)
110
+ # Continue without telemetry rather than crashing
111
+ _telemetry_initialized = True
112
+
113
+
114
+ def get_tracer(name: Optional[str] = None, version: Optional[str] = None):
115
+ """
116
+ Get the OpenTelemetry tracer instance.
117
+
118
+ Args:
119
+ name: Optional tracer name (defaults to service name from config)
120
+ version: Optional tracer version (defaults to service version from config)
121
+
122
+ Returns:
123
+ Tracer instance. Returns a no-op tracer if telemetry is not initialized or disabled.
124
+ """
125
+ global _tracer, _telemetry_initialized
126
+
127
+ if not _telemetry_initialized:
128
+ # Auto-initialize if not done yet
129
+ init_telemetry()
130
+
131
+ if _tracer is None:
132
+ # Return a no-op tracer if telemetry is disabled
133
+ return trace.NoOpTracer()
134
+
135
+ if name or version:
136
+ return trace.get_tracer(name or "qua-libs", version or "1.0.0")
137
+
138
+ return _tracer
@@ -0,0 +1,65 @@
1
+ """
2
+ Context managers for manual span creation.
3
+ """
4
+
5
+ from contextlib import contextmanager
6
+ from typing import Optional, Dict, Any
7
+ from .config import get_tracer
8
+
9
+
10
+ @contextmanager
11
+ def trace_span(
12
+ span_name: str,
13
+ attributes: Optional[Dict[str, Any]] = None,
14
+ tracer_name: Optional[str] = None,
15
+ tracer_version: Optional[str] = None,
16
+ ):
17
+ """
18
+ Context manager for creating a trace span.
19
+
20
+ Args:
21
+ span_name: Name for the span
22
+ attributes: Dictionary of attributes to set on the span
23
+ tracer_name: Optional custom tracer name
24
+ tracer_version: Optional custom tracer version
25
+
26
+ Example:
27
+ with trace_span("process_data", attributes={"component": "processor"}):
28
+ # Your code here
29
+ result = process(data)
30
+ """
31
+ tracer = get_tracer(tracer_name, tracer_version)
32
+
33
+ with tracer.start_as_current_span(span_name) as span:
34
+ if attributes:
35
+ for key, value in attributes.items():
36
+ span.set_attribute(key, value)
37
+ yield span
38
+
39
+
40
+ @contextmanager
41
+ def trace_span_with_attributes(
42
+ span_name: str,
43
+ tracer_name: Optional[str] = None,
44
+ tracer_version: Optional[str] = None,
45
+ ):
46
+ """
47
+ Context manager that yields a span for manual attribute setting.
48
+
49
+ This is useful when you need to set attributes dynamically within the span.
50
+
51
+ Args:
52
+ span_name: Name for the span
53
+ tracer_name: Optional custom tracer name
54
+ tracer_version: Optional custom tracer version
55
+
56
+ Example:
57
+ with trace_span_with_attributes("simulation") as span:
58
+ span.set_attribute("duration", 100)
59
+ span.set_attribute("iterations", 50)
60
+ # Your code here
61
+ """
62
+ tracer = get_tracer(tracer_name, tracer_version)
63
+
64
+ with tracer.start_as_current_span(span_name) as span:
65
+ yield span
@@ -0,0 +1,131 @@
1
+ """
2
+ Decorators for automatic function instrumentation.
3
+ """
4
+
5
+ import functools
6
+ from typing import Callable, Any, Optional, Dict
7
+ from opentelemetry.trace import StatusCode
8
+ from .config import get_tracer
9
+ from .utils import record_exception, set_span_status
10
+
11
+
12
+ def trace_function(
13
+ span_name: Optional[str] = None,
14
+ attributes: Optional[Dict[str, Any]] = None,
15
+ capture_args: bool = False,
16
+ capture_result: bool = False,
17
+ ):
18
+ """
19
+ Decorator to automatically trace a function with OpenTelemetry.
20
+
21
+ Args:
22
+ span_name: Name for the span (defaults to function name)
23
+ attributes: Dictionary of attributes to set on the span
24
+ capture_args: Whether to capture function arguments as span attributes
25
+ capture_result: Whether to capture function return value as span attribute
26
+
27
+ Example:
28
+ @trace_function("process_data", attributes={"component": "data_processor"})
29
+ def process_data(x, y):
30
+ return x + y
31
+
32
+ @trace_function(capture_args=True, capture_result=True)
33
+ def calculate(a, b):
34
+ return a * b
35
+ """
36
+
37
+ def decorator(func: Callable) -> Callable:
38
+ name = span_name or f"{func.__module__}.{func.__name__}"
39
+
40
+ @functools.wraps(func)
41
+ def wrapper(*args, **kwargs):
42
+ tracer = get_tracer()
43
+
44
+ with tracer.start_as_current_span(name) as span:
45
+ # Set initial attributes
46
+ if attributes:
47
+ for key, value in attributes.items():
48
+ span.set_attribute(key, value)
49
+
50
+ # Capture function arguments
51
+ if capture_args:
52
+ for i, arg in enumerate(args):
53
+ span.set_attribute(f"function.arg.{i}", str(arg))
54
+ for key, value in kwargs.items():
55
+ span.set_attribute(f"function.kwarg.{key}", str(value))
56
+
57
+ try:
58
+ result = func(*args, **kwargs)
59
+
60
+ # Capture result
61
+ if capture_result:
62
+ span.set_attribute("function.result", str(result))
63
+
64
+ return result
65
+ except Exception as e:
66
+ record_exception(span, e)
67
+ set_span_status(span, StatusCode.ERROR, str(e))
68
+ raise
69
+
70
+ return wrapper
71
+
72
+ return decorator
73
+
74
+
75
+ def trace_async_function(
76
+ span_name: Optional[str] = None,
77
+ attributes: Optional[Dict[str, Any]] = None,
78
+ capture_args: bool = False,
79
+ capture_result: bool = False,
80
+ ):
81
+ """
82
+ Decorator to automatically trace an async function with OpenTelemetry.
83
+
84
+ Args:
85
+ span_name: Name for the span (defaults to function name)
86
+ attributes: Dictionary of attributes to set on the span
87
+ capture_args: Whether to capture function arguments as span attributes
88
+ capture_result: Whether to capture function return value as span attribute
89
+
90
+ Example:
91
+ @trace_async_function("async_process")
92
+ async def async_process(data):
93
+ return await process(data)
94
+ """
95
+
96
+ def decorator(func: Callable) -> Callable:
97
+ name = span_name or f"{func.__module__}.{func.__name__}"
98
+
99
+ @functools.wraps(func)
100
+ async def wrapper(*args, **kwargs):
101
+ tracer = get_tracer()
102
+
103
+ with tracer.start_as_current_span(name) as span:
104
+ # Set initial attributes
105
+ if attributes:
106
+ for key, value in attributes.items():
107
+ span.set_attribute(key, value)
108
+
109
+ # Capture function arguments
110
+ if capture_args:
111
+ for i, arg in enumerate(args):
112
+ span.set_attribute(f"function.arg.{i}", str(arg))
113
+ for key, value in kwargs.items():
114
+ span.set_attribute(f"function.kwarg.{key}", str(value))
115
+
116
+ try:
117
+ result = await func(*args, **kwargs)
118
+
119
+ # Capture result
120
+ if capture_result:
121
+ span.set_attribute("function.result", str(result))
122
+
123
+ return result
124
+ except Exception as e:
125
+ record_exception(span, e)
126
+ set_span_status(span, StatusCode.ERROR, str(e))
127
+ raise
128
+
129
+ return wrapper
130
+
131
+ return decorator
@@ -0,0 +1,137 @@
1
+ """
2
+ Load project-level telemetry settings from ``.qua-libs/telemetry.toml``.
3
+
4
+ Create this file at the repository root:
5
+
6
+ ``<install>/.qua-libs/telemetry.toml``
7
+
8
+ Discovery walks upward from the current working directory.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import os
14
+ import sys
15
+ from pathlib import Path
16
+ from typing import Any, Mapping, Optional
17
+
18
+ from .config import TelemetryConfig
19
+
20
+ CONFIG_DIR_NAME = ".qua-libs"
21
+ CONFIG_FILE_NAME = "telemetry.toml"
22
+ ENV_CONFIG_PATH = "QUA_LIBS_TELEMETRY_CONFIG"
23
+
24
+
25
+ def _load_toml(path: Path) -> dict[str, Any]:
26
+ if sys.version_info >= (3, 11):
27
+ import tomllib
28
+
29
+ loader = tomllib.load
30
+ else:
31
+ import tomli
32
+
33
+ loader = tomli.load
34
+
35
+ with path.open("rb") as handle:
36
+ return loader(handle)
37
+
38
+
39
+ def _as_bool(value: Any) -> bool:
40
+ if isinstance(value, bool):
41
+ return value
42
+ if isinstance(value, str):
43
+ return value.lower() in ("true", "1", "yes")
44
+ return bool(value)
45
+
46
+
47
+ def find_telemetry_config_file(start: Optional[Path] = None) -> Optional[Path]:
48
+ """
49
+ Locate the project telemetry config file.
50
+
51
+ Search order:
52
+ 1. ``QUA_LIBS_TELEMETRY_CONFIG`` env var (explicit path)
53
+ 2. Walk upward from *start* (default: cwd) for ``.qua-libs/telemetry.toml``
54
+ """
55
+ env_path = os.getenv(ENV_CONFIG_PATH)
56
+ if env_path:
57
+ path = Path(env_path).expanduser()
58
+ return path if path.is_file() else None
59
+
60
+ current = (start or Path.cwd()).resolve()
61
+ for directory in (current, *current.parents):
62
+ candidate = directory / CONFIG_DIR_NAME / CONFIG_FILE_NAME
63
+ if candidate.is_file():
64
+ return candidate
65
+ return None
66
+
67
+
68
+ def load_telemetry_file_config(start: Optional[Path] = None) -> Optional[dict[str, Any]]:
69
+ """Return the ``[telemetry]`` table from the project config file, if present."""
70
+ path = find_telemetry_config_file(start)
71
+ if path is None:
72
+ return None
73
+
74
+ data = _load_toml(path)
75
+ section = data.get("telemetry")
76
+ if section is None:
77
+ return None
78
+ if not isinstance(section, dict):
79
+ raise ValueError(f"{path}: [telemetry] must be a table")
80
+ return section
81
+
82
+
83
+ def _resolve_enabled(file_value: Any, default: bool) -> bool:
84
+ env = os.getenv("UPTRACE_ENABLED")
85
+ if env is not None:
86
+ return env.lower() in ("true", "1", "yes")
87
+ if file_value is not None:
88
+ return _as_bool(file_value)
89
+ return default
90
+
91
+
92
+ def _resolve_str(file_value: Any, env_name: str, default: str) -> str:
93
+ env = os.getenv(env_name)
94
+ if env:
95
+ return env
96
+ if file_value is not None:
97
+ return str(file_value)
98
+ return default
99
+
100
+
101
+ def _resolve_optional_str(file_value: Any, env_name: str) -> Optional[str]:
102
+ env = os.getenv(env_name)
103
+ if env:
104
+ return env
105
+ if file_value is not None:
106
+ return str(file_value)
107
+ return None
108
+
109
+
110
+ def build_project_config(
111
+ *,
112
+ defaults: Mapping[str, Any],
113
+ file_values: Optional[Mapping[str, Any]] = None,
114
+ ) -> TelemetryConfig:
115
+ """
116
+ Build a :class:`TelemetryConfig` from defaults, an optional TOML file, and env vars.
117
+
118
+ Environment variables override file values; file values override *defaults*.
119
+ """
120
+ file_values = file_values or {}
121
+
122
+ resource_attributes = file_values.get("resource_attributes")
123
+ if resource_attributes is not None and not isinstance(resource_attributes, dict):
124
+ raise ValueError("[telemetry].resource_attributes must be a table")
125
+
126
+ return TelemetryConfig(
127
+ dsn=_resolve_optional_str(file_values.get("dsn"), "UPTRACE_DSN"),
128
+ service_name=_resolve_str(file_values.get("service_name"), "UPTRACE_SERVICE_NAME", defaults["service_name"]),
129
+ service_version=_resolve_str(
130
+ file_values.get("service_version"), "UPTRACE_SERVICE_VERSION", defaults["service_version"]
131
+ ),
132
+ deployment_environment=_resolve_str(
133
+ file_values.get("deployment_environment"), "UPTRACE_ENV", defaults["deployment_environment"]
134
+ ),
135
+ enabled=_resolve_enabled(file_values.get("enabled"), defaults.get("enabled", False)),
136
+ resource_attributes=resource_attributes or {},
137
+ )
@@ -0,0 +1,33 @@
1
+ """
2
+ Project-wide telemetry configuration.
3
+
4
+ Telemetry is off by default. Enable it with ``.qua-libs/telemetry.toml`` or
5
+ environment variables (``UPTRACE_ENABLED``, ``UPTRACE_DSN``, …).
6
+
7
+ Resolution order per setting: environment variables, then TOML, then the defaults
8
+ below.
9
+ """
10
+
11
+ from pathlib import Path
12
+ from typing import Optional
13
+
14
+ from .config import TelemetryConfig
15
+ from .file_config import build_project_config, load_telemetry_file_config
16
+
17
+ _PROJECT_DEFAULTS = {
18
+ "service_name": "qua-libs",
19
+ "service_version": "1.0.0",
20
+ "deployment_environment": "production",
21
+ "enabled": False,
22
+ }
23
+
24
+
25
+ def load_project_config(start: Optional[Path] = None) -> TelemetryConfig:
26
+ """Load telemetry settings from defaults, TOML, and environment variables."""
27
+ return build_project_config(
28
+ defaults=_PROJECT_DEFAULTS,
29
+ file_values=load_telemetry_file_config(start),
30
+ )
31
+
32
+
33
+ PROJECT_CONFIG = load_project_config()
@@ -0,0 +1,105 @@
1
+ """
2
+ Utility functions for working with spans.
3
+ """
4
+
5
+ from typing import Any, Optional
6
+ from opentelemetry.trace import Span, Status, StatusCode
7
+
8
+
9
+ def set_span_attribute(span: Span, key: str, value: Any) -> None:
10
+ """
11
+ Set an attribute on a span.
12
+
13
+ Args:
14
+ span: The span to set the attribute on
15
+ key: Attribute key
16
+ value: Attribute value (will be converted to string if not a supported type)
17
+
18
+ Example:
19
+ with trace_span("operation") as span:
20
+ set_span_attribute(span, "user.id", user_id)
21
+ """
22
+ span.set_attribute(key, value)
23
+
24
+
25
+ def add_span_event(span: Span, name: str, attributes: Optional[dict] = None) -> None:
26
+ """
27
+ Add an event to a span.
28
+
29
+ Args:
30
+ span: The span to add the event to
31
+ name: Event name
32
+ attributes: Optional dictionary of event attributes
33
+
34
+ Example:
35
+ with trace_span("operation") as span:
36
+ add_span_event(span, "checkpoint_reached", {"checkpoint": 1})
37
+ """
38
+ span.add_event(name, attributes or {})
39
+
40
+
41
+ def record_exception(span: Span, exception: Exception, attributes: Optional[dict] = None) -> None:
42
+ """
43
+ Record an exception on a span.
44
+
45
+ Args:
46
+ span: The span to record the exception on
47
+ exception: The exception to record
48
+ attributes: Optional additional attributes
49
+
50
+ Example:
51
+ try:
52
+ risky_operation()
53
+ except Exception as e:
54
+ with trace_span("operation") as span:
55
+ record_exception(span, e)
56
+ raise
57
+ """
58
+ span.record_exception(exception, attributes)
59
+
60
+
61
+ def set_span_status(
62
+ span: Span,
63
+ status_code: StatusCode,
64
+ description: Optional[str] = None,
65
+ ) -> None:
66
+ """
67
+ Set the status of a span.
68
+
69
+ Args:
70
+ span: The span to set the status on
71
+ status_code: StatusCode (OK, ERROR, UNSET)
72
+ description: Optional status description
73
+
74
+ Example:
75
+ with trace_span("operation") as span:
76
+ try:
77
+ result = operation()
78
+ set_span_status(span, StatusCode.OK)
79
+ except Exception as e:
80
+ set_span_status(span, StatusCode.ERROR, str(e))
81
+ """
82
+ span.set_status(Status(status_code, description))
83
+
84
+
85
+ def get_current_span() -> Span:
86
+ """
87
+ Get the currently active telemetry span.
88
+
89
+ Use this inside any @node.run_action function that has been
90
+ instrumented with instrument_calibration_node() to access the
91
+ span and set custom attributes dynamically.
92
+
93
+ Returns:
94
+ The current active span, or a no-op span if none is active.
95
+
96
+ Example:
97
+ @node.run_action(skip_if=node.parameters.simulate)
98
+ def analyse_data(node):
99
+ span = get_current_span()
100
+ # ... do analysis ...
101
+ set_span_attribute(span, "fit.q1", "successful")
102
+ """
103
+ from opentelemetry import trace
104
+
105
+ return trace.get_current_span()