From 786c5d8b584d66ee755e3eadbc971c47533625b1 Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Thu, 15 Aug 2024 11:59:06 -0700 Subject: [PATCH 01/41] Update README.md --- PyTorch2Jax/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/PyTorch2Jax/README.md b/PyTorch2Jax/README.md index 29a7699..fff7df5 100644 --- a/PyTorch2Jax/README.md +++ b/PyTorch2Jax/README.md @@ -1,3 +1,5 @@ # PyTorch to Jax Conversion -This example illustrates how Benchify can be used to test the equivalence of two austensibly equivalent functions. In this case, the customer translated some code from PyTorch to Jax, and wanted to make sure that the two implementations were functionally equivalent. Thank you to [Nithin Santi](https://www.linkedin.com/in/nithinsonti/) for contributing this example! \ No newline at end of file +This example illustrates how Benchify can be used to test the equivalence of two austensibly equivalent functions. In this case, the customer translated some code from PyTorch to Jax, and wanted to make sure that the two implementations were functionally equivalent. Thank you to [Nithin Santi](https://www.linkedin.com/in/nithinsonti/) for contributing this example! + +Read the report [here](https://github.com/maxvonhippel/benchify-examples/pull/20). We're working on formatting improvements, and will share updates on this thread as they ship. From 76d48e133c4c1b4e0cdc3df023d6dd9c7569f338 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Casta=C3=B1o?= Date: Fri, 23 Aug 2024 15:36:02 -0700 Subject: [PATCH 02/41] triggering pull request --- PyTorch2Jax/script.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/PyTorch2Jax/script.py b/PyTorch2Jax/script.py index fe0e4f6..4bfdd7c 100644 --- a/PyTorch2Jax/script.py +++ b/PyTorch2Jax/script.py @@ -19,6 +19,7 @@ def reshape_for_broadcast(freqs_cis: torch.Tensor, x: torch.Tensor): The functions should be functionally equivalent. """ + # This should be equivalent to the below function (apply_rotary_emb_jax) def apply_rotary_emb_torch( xq: torch.Tensor, @@ -32,6 +33,7 @@ def apply_rotary_emb_torch( xk_out = torch.view_as_real(xk_ * freqs_cis).flatten(3) return xq_out.type_as(xq), xk_out.type_as(xk) + # This should be equivalent to the above function (apply_rotary_emb_torch) def apply_rotary_emb_jax( xq: jnp.ndarray, @@ -66,6 +68,7 @@ def apply_rotary_emb_jax( def jnp_ndarray_to_torch(x: jnp.ndarray) -> torch.Tensor: return torch.from_numpy(x.astype(np.float32)) + def torch_tensor_to_jnp(x: torch.Tensor) -> jnp.ndarray: return x.cpu().numpy().astype(np.float32) From 34c34188fd64eae5f6e82a87b7b0175f8da7ac5a Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Fri, 30 Aug 2024 15:29:03 -0700 Subject: [PATCH 03/41] add leetcode example with edit distance --- LeetCode/script.py | 56 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 LeetCode/script.py diff --git a/LeetCode/script.py b/LeetCode/script.py new file mode 100644 index 0000000..db432c0 --- /dev/null +++ b/LeetCode/script.py @@ -0,0 +1,56 @@ +""" +Given two strings word1 and word2, return the minimum number of operations +required to convert word1 to word2. +You have the following three operations permitted on a word: +Insert a character +Delete a character +Replace a character + +Example 1: + +Input: word1 = "horse", word2 = "ros" +Output: 3 +Explanation: +horse -> rorse (replace 'h' with 'r') +rorse -> rose (remove 'r') +rose -> ros (remove 'e') +Example 2: +Input: word1 = "intention", word2 = "execution"Output: 5Explanation: +intention -> inention (remove 't') +inention -> enention (replace 'i' with 'e') +enention -> exention (replace 'n' with 'x') +exention -> exection (replace 'n' with 'c') +exection -> execution (insert 'u') + +Constraints: + +0 <= word1.length, word2.length <= 500 +word1 and word2 consist of lowercase English letters. +""" +class Solution(object): + def minDistance(self, word1, word2): + """ + :type word1: str + :type word2: str + :rtype: int + """ + m = len(word1) + n = len(word2) + + dp = [[0] * n for _ in range(m + 1)] + + # Base cases + for i in range(1, m): + dp[i][0] = i + for j in range(1, n): + dp[0][j] = j + + # Recurrence relation + for i in range(1, m): + for j in range(1, n): + if word1[i - 1] == word2[j - 1]: + dp[i][j] = dp[i - 1][j - 1] + else: + dp[i][j] = min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + 1) + + return dp[m][n] \ No newline at end of file From 82247461797dc3a939a9da45fec1e1510c00c478 Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Sun, 1 Sep 2024 15:32:47 -0700 Subject: [PATCH 04/41] saving new logic --- LeetCode/script.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/LeetCode/script.py b/LeetCode/script.py index db432c0..c643d3d 100644 --- a/LeetCode/script.py +++ b/LeetCode/script.py @@ -15,7 +15,9 @@ rorse -> rose (remove 'r') rose -> ros (remove 'e') Example 2: -Input: word1 = "intention", word2 = "execution"Output: 5Explanation: +Input: word1 = "intention", word2 = "execution" +Output: 5 +Explanation: intention -> inention (remove 't') inention -> enention (replace 'i' with 'e') enention -> exention (replace 'n' with 'x') From 94332fbfd0d7179872c8445f2f2283f5b9d2f62f Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Sun, 1 Sep 2024 15:34:00 -0700 Subject: [PATCH 05/41] trigger leetcode run --- LeetCode/script.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/LeetCode/script.py b/LeetCode/script.py index c643d3d..c6acbd1 100644 --- a/LeetCode/script.py +++ b/LeetCode/script.py @@ -30,12 +30,14 @@ word1 and word2 consist of lowercase English letters. """ class Solution(object): + def minDistance(self, word1, word2): """ :type word1: str :type word2: str :rtype: int """ + m = len(word1) n = len(word2) @@ -46,7 +48,6 @@ def minDistance(self, word1, word2): dp[i][0] = i for j in range(1, n): dp[0][j] = j - # Recurrence relation for i in range(1, m): for j in range(1, n): From c1d762bff500af8c24ce0b4be1dec961d10c9de9 Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Sun, 1 Sep 2024 15:55:18 -0700 Subject: [PATCH 06/41] Fix the error to be better --- LeetCode/script.py | 86 +++++++++++++++------------------------------- 1 file changed, 28 insertions(+), 58 deletions(-) diff --git a/LeetCode/script.py b/LeetCode/script.py index c6acbd1..d03f173 100644 --- a/LeetCode/script.py +++ b/LeetCode/script.py @@ -1,59 +1,29 @@ -""" -Given two strings word1 and word2, return the minimum number of operations -required to convert word1 to word2. -You have the following three operations permitted on a word: -Insert a character -Delete a character -Replace a character - -Example 1: - -Input: word1 = "horse", word2 = "ros" -Output: 3 -Explanation: -horse -> rorse (replace 'h' with 'r') -rorse -> rose (remove 'r') -rose -> ros (remove 'e') -Example 2: -Input: word1 = "intention", word2 = "execution" -Output: 5 -Explanation: -intention -> inention (remove 't') -inention -> enention (replace 'i' with 'e') -enention -> exention (replace 'n' with 'x') -exention -> exection (replace 'n' with 'c') -exection -> execution (insert 'u') - -Constraints: - -0 <= word1.length, word2.length <= 500 -word1 and word2 consist of lowercase English letters. -""" -class Solution(object): +def minDistance(word1, word2): - def minDistance(self, word1, word2): - """ - :type word1: str - :type word2: str - :rtype: int - """ - - m = len(word1) - n = len(word2) - - dp = [[0] * n for _ in range(m + 1)] - - # Base cases - for i in range(1, m): - dp[i][0] = i - for j in range(1, n): - dp[0][j] = j - # Recurrence relation - for i in range(1, m): - for j in range(1, n): - if word1[i - 1] == word2[j - 1]: - dp[i][j] = dp[i - 1][j - 1] - else: - dp[i][j] = min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + 1) - - return dp[m][n] \ No newline at end of file + """ + :type word1: str + :type word2: str + :rtype: int + """ + m = len(word1) + n = len(word2) + + # Initialize dp array of size (m+1) x (n+1) + dp = [[0] * (n + 1) for _ in range(m + 1)] + + # Base cases: Transforming from empty string to word1 and word2 + for i in range(m + 1): + dp[i][0] = i + for j in range(n + 1): + dp[0][j] = j + + for i in range(1, m + 1): + for j in range(1, n + 1): + if word1[i - 1] == word2[j - 1] or (i > 1 and word1[i - 2] == word2[j - 1]): + dp[i][j] = dp[i - 1][j - 1] + else: # Characters don't match + dp[i][j] = min(dp[i - 1][j] + 1, # Delete + dp[i][j - 1] + 1, # Insert + dp[i - 1][j - 1] + 1) # Replace + + return dp[m][n] From 907efc04ee686709282b5ae39c72cd81d315531d Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Mon, 2 Sep 2024 14:47:19 -0700 Subject: [PATCH 07/41] improved comment for better demo --- LeetCode/script.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/LeetCode/script.py b/LeetCode/script.py index d03f173..5a78f82 100644 --- a/LeetCode/script.py +++ b/LeetCode/script.py @@ -1,5 +1,6 @@ -def minDistance(word1, word2): - +# Returns an edit distance which satisfies all the rules of a metric space. +# The possible edits are delete, insert, and replace. +def minDistance(word1, word2): """ :type word1: str :type word2: str @@ -14,16 +15,17 @@ def minDistance(word1, word2): # Base cases: Transforming from empty string to word1 and word2 for i in range(m + 1): dp[i][0] = i + for j in range(n + 1): dp[0][j] = j for i in range(1, m + 1): for j in range(1, n + 1): - if word1[i - 1] == word2[j - 1] or (i > 1 and word1[i - 2] == word2[j - 1]): + if word1[i - 1] == word2[j - 1] or word1[i - 2] == word2[j - 1]: dp[i][j] = dp[i - 1][j - 1] - else: # Characters don't match dp[i][j] = min(dp[i - 1][j] + 1, # Delete - dp[i][j - 1] + 1, # Insert - dp[i - 1][j - 1] + 1) # Replace + dp[i][j - 1] + 1, # Insert + dp[i - 1][j - 1] + 1) # Replace return dp[m][n] + From 5c867e6b8433045f648e48ed34804a228501f879 Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Mon, 2 Sep 2024 14:48:00 -0700 Subject: [PATCH 08/41] improved comment --- LeetCode/script.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/LeetCode/script.py b/LeetCode/script.py index 5a78f82..8bdac3b 100644 --- a/LeetCode/script.py +++ b/LeetCode/script.py @@ -1,11 +1,8 @@ # Returns an edit distance which satisfies all the rules of a metric space. +# The inputs are both strings and the output is a non-negative integer. # The possible edits are delete, insert, and replace. -def minDistance(word1, word2): - """ - :type word1: str - :type word2: str - :rtype: int - """ +def minDistance(word1, word2): + m = len(word1) n = len(word2) From fe1498f6320c2ae18736f5242c254ef4e1fb71ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Casta=C3=B1o?= Date: Mon, 2 Sep 2024 20:25:40 -0700 Subject: [PATCH 09/41] Remove LeetCode stuff for better diff --- LeetCode/script.py | 28 ---------------------------- 1 file changed, 28 deletions(-) delete mode 100644 LeetCode/script.py diff --git a/LeetCode/script.py b/LeetCode/script.py deleted file mode 100644 index 8bdac3b..0000000 --- a/LeetCode/script.py +++ /dev/null @@ -1,28 +0,0 @@ -# Returns an edit distance which satisfies all the rules of a metric space. -# The inputs are both strings and the output is a non-negative integer. -# The possible edits are delete, insert, and replace. -def minDistance(word1, word2): - - m = len(word1) - n = len(word2) - - # Initialize dp array of size (m+1) x (n+1) - dp = [[0] * (n + 1) for _ in range(m + 1)] - - # Base cases: Transforming from empty string to word1 and word2 - for i in range(m + 1): - dp[i][0] = i - - for j in range(n + 1): - dp[0][j] = j - - for i in range(1, m + 1): - for j in range(1, n + 1): - if word1[i - 1] == word2[j - 1] or word1[i - 2] == word2[j - 1]: - dp[i][j] = dp[i - 1][j - 1] - dp[i][j] = min(dp[i - 1][j] + 1, # Delete - dp[i][j - 1] + 1, # Insert - dp[i - 1][j - 1] + 1) # Replace - - return dp[m][n] - From 87728275eb2ac410212d55e31446cda88466f4eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Casta=C3=B1o?= Date: Mon, 2 Sep 2024 20:29:04 -0700 Subject: [PATCH 10/41] Fix gitignore so we dont accidentally push pytest stuff --- .gitignore | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) diff --git a/.gitignore b/.gitignore index 775df55..7df3b3d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,164 @@ .DS_Store .hypothesis/ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/latest/usage/project/#working-with-version-control +.pdm.toml +.pdm-python +.pdm-build/ + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +.idea/ \ No newline at end of file From 9bbaabce4827cdebc0c11481ecde8ad05426a7cf Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Mon, 2 Sep 2024 23:48:56 -0700 Subject: [PATCH 11/41] reduce the requirements for rapid prototyping --- requirements.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 920141e..24ce15a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1 @@ -torch numpy -jax From 1de770f9e1699cd9e0a54596a720d8ed7ad4f253 Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Tue, 3 Sep 2024 00:12:21 -0700 Subject: [PATCH 12/41] add minDistance --- LeetCode/script.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 LeetCode/script.py diff --git a/LeetCode/script.py b/LeetCode/script.py new file mode 100644 index 0000000..cdda946 --- /dev/null +++ b/LeetCode/script.py @@ -0,0 +1,27 @@ +# Returns an edit distance which satisfies all the rules of a metric space. +# The inputs are both strings and the output is a non-negative integer. +# The possible edits are delete, insert, and replace. +def minDistance(word1, word2): + + m = len(word1) + n = len(word2) + + # Initialize dp array of size (m+1) x (n+1) + dp = [[0] * (n + 1) for _ in range(m + 1)] + + # Base cases: Transforming from empty string to word1 and word2 + for i in range(m + 1): + dp[i][0] = i + + for j in range(n + 1): + dp[0][j] = j + + for i in range(1, m + 1): + for j in range(1, n + 1): + if word1[i - 1] == word2[j - 1]: + dp[i][j] = dp[i - 1][j - 1] + dp[i][j] = min(dp[i - 1][j] + 1, # Delete + dp[i][j - 1] + 1, # Insert + dp[i - 1][j - 1] + 1) # Replace + + return dp[m][n] From 85ad6012c2112b024b8210a85e8765888ca178ee Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Fri, 20 Sep 2024 12:28:39 -0700 Subject: [PATCH 13/41] Wrote commit with aws mocks ... first test run now --- AWS/script.py | 90 ++++++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 3 ++ 2 files changed, 93 insertions(+) create mode 100644 AWS/script.py diff --git a/AWS/script.py b/AWS/script.py new file mode 100644 index 0000000..d9cbc81 --- /dev/null +++ b/AWS/script.py @@ -0,0 +1,90 @@ +import boto3 +import json +import pulp +import logging +from datetime import datetime + +# Initialize AWS clients +cloudwatch = boto3.client('cloudwatch') +kinesis = boto3.client('kinesis') + +def put_metric_data(metric_name, value, unit): + """Put custom metric data to CloudWatch""" + cloudwatch.put_metric_data( + Namespace='CustomMetrics', + MetricData=[ + { + 'MetricName': metric_name, + 'Value': value, + 'Unit': unit, + 'Timestamp': datetime.utcnow() + } + ] + ) + +def put_record_to_kinesis(stream_name, data): + """Put a record to Kinesis Data Stream""" + response = kinesis.put_record( + StreamName=stream_name, + Data=json.dumps(data), + PartitionKey=str(datetime.utcnow().timestamp()) + ) + return response + + +def optimize_production(): + """Optimize production using linear programming and log the results""" + # Set up logging + logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + logger = logging.getLogger(__name__) + + # Create the LP problem + prob = pulp.LpProblem("Production Optimization", pulp.LpMaximize) + + # Define variables + x1 = pulp.LpVariable("Product_1", lowBound=0) + x2 = pulp.LpVariable("Product_2", lowBound=0) + + # Define the objective function + prob += 20 * x1 + 30 * x2, "Profit" + + # Define constraints + prob += 2 * x1 + 3 * x2 <= 100, "Labor_hours" + prob += 4 * x1 + 3 * x2 <= 120, "Material_units" + + # Solve the problem + prob.solve() + + # Log the results + logger.info("Status: %s" % pulp.LpStatus[prob.status]) + logger.info("Optimal Production Plan:") + logger.info("Product 1: %s units" % x1.varValue) + logger.info("Product 2: %s units" % x2.varValue) + logger.info("Total Profit: $%s" % pulp.value(prob.objective)) + + # Send the results to Kinesis + stream_name = 'ProductionOptimizationResults' + data = { + 'timestamp': str(datetime.utcnow()), + 'status': pulp.LpStatus[prob.status], + 'product1': x1.varValue, + 'product2': x2.varValue, + 'total_profit': pulp.value(prob.objective) + } + response = put_record_to_kinesis(stream_name, data) + logger.info(f"Optimization results sent to Kinesis. Shard ID: {response['ShardId']}") + + + +if __name__ == "__main__": + # Put a custom metric to CloudWatch + put_metric_data('MyCustomMetric', 42, 'Count') + + # Put a record to Kinesis Data Stream + stream_name = 'MyKinesisStream' + data = { + 'timestamp': str(datetime.utcnow()), + 'message': 'Hello, Kinesis!' + } + response = put_record_to_kinesis(stream_name, data) + print(f"Record sent to Kinesis. Shard ID: {response['ShardId']}") diff --git a/requirements.txt b/requirements.txt index 24ce15a..b02cdf9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,4 @@ numpy +boto3 +pulp +logging \ No newline at end of file From e1e24078753a29df2617eb7f599d980c1cc23d53 Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Sat, 21 Sep 2024 11:24:38 -0700 Subject: [PATCH 14/41] improve aws test --- AWS/script.py | 58 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/AWS/script.py b/AWS/script.py index d9cbc81..b6886ff 100644 --- a/AWS/script.py +++ b/AWS/script.py @@ -31,12 +31,24 @@ def put_record_to_kinesis(stream_name, data): ) return response +def log_to_cloudwatch(log_group, log_stream, message): + """Log a message to CloudWatch""" + timestamp = int(datetime.utcnow().timestamp() * 1000) + cloudwatch.put_log_events( + logGroupName=log_group, + logStreamName=log_stream, + logEvents=[ + { + 'timestamp': timestamp, + 'message': message + } + ] + ) def optimize_production(): - """Optimize production using linear programming and log the results""" - # Set up logging - logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') - logger = logging.getLogger(__name__) + """Optimize production using linear programming and log the results to CloudWatch""" + log_group = 'ProductionOptimizationLogs' + log_stream = 'OptimizationResults' # Create the LP problem prob = pulp.LpProblem("Production Optimization", pulp.LpMaximize) @@ -55,26 +67,38 @@ def optimize_production(): # Solve the problem prob.solve() - # Log the results - logger.info("Status: %s" % pulp.LpStatus[prob.status]) - logger.info("Optimal Production Plan:") - logger.info("Product 1: %s units" % x1.varValue) - logger.info("Product 2: %s units" % x2.varValue) - logger.info("Total Profit: $%s" % pulp.value(prob.objective)) + # Prepare the results + status = pulp.LpStatus[prob.status] + product1 = x1.varValue + product2 = x2.varValue + total_profit = pulp.value(prob.objective) + + # Log the results to CloudWatch + log_to_cloudwatch(log_group, log_stream, f"Status: {status}") + log_to_cloudwatch(log_group, log_stream, "Optimal Production Plan:") + log_to_cloudwatch(log_group, log_stream, f"Product 1: {product1} units") + log_to_cloudwatch(log_group, log_stream, f"Product 2: {product2} units") + log_to_cloudwatch(log_group, log_stream, f"Total Profit: ${total_profit}") # Send the results to Kinesis stream_name = 'ProductionOptimizationResults' data = { 'timestamp': str(datetime.utcnow()), - 'status': pulp.LpStatus[prob.status], - 'product1': x1.varValue, - 'product2': x2.varValue, - 'total_profit': pulp.value(prob.objective) + 'status': status, + 'product1': product1, + 'product2': product2, + 'total_profit': total_profit } response = put_record_to_kinesis(stream_name, data) - logger.info(f"Optimization results sent to Kinesis. Shard ID: {response['ShardId']}") - - + log_to_cloudwatch(log_group, log_stream, f"Optimization results sent to Kinesis. Shard ID: {response['ShardId']}") + + # Return the results + return { + 'status': status, + 'product1': product1, + 'product2': product2, + 'total_profit': total_profit + } if __name__ == "__main__": # Put a custom metric to CloudWatch From 6e6266ba2854735a6c89f7104c3c18bb45f76804 Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Sat, 21 Sep 2024 15:58:15 -0700 Subject: [PATCH 15/41] Fix utc now thing for demo --- AWS/script.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/AWS/script.py b/AWS/script.py index b6886ff..e6a4dad 100644 --- a/AWS/script.py +++ b/AWS/script.py @@ -1,8 +1,7 @@ import boto3 import json import pulp -import logging -from datetime import datetime +from datetime import datetime, timezone # Initialize AWS clients cloudwatch = boto3.client('cloudwatch') @@ -17,7 +16,7 @@ def put_metric_data(metric_name, value, unit): 'MetricName': metric_name, 'Value': value, 'Unit': unit, - 'Timestamp': datetime.utcnow() + 'Timestamp': datetime.now(timezone.utc) # Fixed here } ] ) @@ -27,13 +26,13 @@ def put_record_to_kinesis(stream_name, data): response = kinesis.put_record( StreamName=stream_name, Data=json.dumps(data), - PartitionKey=str(datetime.utcnow().timestamp()) + PartitionKey=str(datetime.now(timezone.utc).timestamp()) # Fixed here ) return response def log_to_cloudwatch(log_group, log_stream, message): """Log a message to CloudWatch""" - timestamp = int(datetime.utcnow().timestamp() * 1000) + timestamp = int(datetime.now(timezone.utc).timestamp() * 1000) # Fixed here cloudwatch.put_log_events( logGroupName=log_group, logStreamName=log_stream, @@ -83,7 +82,7 @@ def optimize_production(): # Send the results to Kinesis stream_name = 'ProductionOptimizationResults' data = { - 'timestamp': str(datetime.utcnow()), + 'timestamp': str(datetime.now(timezone.utc)), # Fixed here 'status': status, 'product1': product1, 'product2': product2, @@ -107,7 +106,7 @@ def optimize_production(): # Put a record to Kinesis Data Stream stream_name = 'MyKinesisStream' data = { - 'timestamp': str(datetime.utcnow()), + 'timestamp': str(datetime.now(timezone.utc)), # Fixed here 'message': 'Hello, Kinesis!' } response = put_record_to_kinesis(stream_name, data) From 6d990e69cbf352fdf0ded61e68cd64bbc780919d Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Sat, 21 Sep 2024 18:47:35 -0700 Subject: [PATCH 16/41] Delete bad requirement and add some newlines ins cript --- AWS/script.py | 4 ++++ requirements.txt | 3 +-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/AWS/script.py b/AWS/script.py index e6a4dad..748715c 100644 --- a/AWS/script.py +++ b/AWS/script.py @@ -9,6 +9,7 @@ def put_metric_data(metric_name, value, unit): """Put custom metric data to CloudWatch""" + cloudwatch.put_metric_data( Namespace='CustomMetrics', MetricData=[ @@ -23,6 +24,7 @@ def put_metric_data(metric_name, value, unit): def put_record_to_kinesis(stream_name, data): """Put a record to Kinesis Data Stream""" + response = kinesis.put_record( StreamName=stream_name, Data=json.dumps(data), @@ -32,6 +34,7 @@ def put_record_to_kinesis(stream_name, data): def log_to_cloudwatch(log_group, log_stream, message): """Log a message to CloudWatch""" + timestamp = int(datetime.now(timezone.utc).timestamp() * 1000) # Fixed here cloudwatch.put_log_events( logGroupName=log_group, @@ -46,6 +49,7 @@ def log_to_cloudwatch(log_group, log_stream, message): def optimize_production(): """Optimize production using linear programming and log the results to CloudWatch""" + log_group = 'ProductionOptimizationLogs' log_stream = 'OptimizationResults' diff --git a/requirements.txt b/requirements.txt index b02cdf9..d11e438 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,3 @@ numpy boto3 -pulp -logging \ No newline at end of file +pulp \ No newline at end of file From 6e8215aa8250a379e6dfb5453f6c43753c2802ac Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Sat, 21 Sep 2024 20:04:44 -0700 Subject: [PATCH 17/41] Clean up script again to fix log calling for cloudwatch demo, add newline to trigger --- AWS/script.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/AWS/script.py b/AWS/script.py index 748715c..ff89a92 100644 --- a/AWS/script.py +++ b/AWS/script.py @@ -2,6 +2,7 @@ import json import pulp from datetime import datetime, timezone +import time # Initialize AWS clients cloudwatch = boto3.client('cloudwatch') @@ -28,26 +29,25 @@ def put_record_to_kinesis(stream_name, data): response = kinesis.put_record( StreamName=stream_name, Data=json.dumps(data), - PartitionKey=str(datetime.now(timezone.utc).timestamp()) # Fixed here + PartitionKey=str(datetime.now(timezone.utc).timestamp()) ) return response def log_to_cloudwatch(log_group, log_stream, message): - """Log a message to CloudWatch""" - - timestamp = int(datetime.now(timezone.utc).timestamp() * 1000) # Fixed here - cloudwatch.put_log_events( + cloudwatch_logs = boto3.client('logs') + cloudwatch_logs.put_log_events( logGroupName=log_group, logStreamName=log_stream, logEvents=[ { - 'timestamp': timestamp, - 'message': message - } + 'timestamp': int(time.time() * 1000), + 'message': message, + }, ] ) def optimize_production(): + """Optimize production using linear programming and log the results to CloudWatch""" log_group = 'ProductionOptimizationLogs' From 9ed8e4366973c06a30b4bea1cea22b03fea30cc4 Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Sun, 22 Sep 2024 14:31:00 -0700 Subject: [PATCH 18/41] initial version of redis mocking test --- Redis/script.py | 31 +++++++++++++++++++++++++++++++ requirements.txt | 3 ++- 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 Redis/script.py diff --git a/Redis/script.py b/Redis/script.py new file mode 100644 index 0000000..ed0f048 --- /dev/null +++ b/Redis/script.py @@ -0,0 +1,31 @@ +import redis + +def redis_operations(): + # Create a Redis client + redis_client = redis.Redis(host='localhost', port=6379, db=0) + + # Set a key-value pair + redis_client.set('greeting', 'Hello, Redis!') + + # Get the value for a key + value = redis_client.get('greeting') + print(value.decode('utf-8')) # Decode bytes to string + + # Increment a counter + redis_client.incr('visitor_count') + + # Get the current count + count = redis_client.get('visitor_count') + print(f"Visitor count: {count.decode('utf-8')}") + + # Delete a key + redis_client.delete('greeting') + + # Check if a key exists + exists = redis_client.exists('greeting') + print(f"Does 'greeting' exist? {exists}") + +# Call the function to execute Redis operations +if __name__ == "__main__": + redis_operations() + diff --git a/requirements.txt b/requirements.txt index d11e438..afa472f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ numpy boto3 -pulp \ No newline at end of file +pulp +redis \ No newline at end of file From bdf5852c0fdae58ba2ba76cb69bae2e683aa3955 Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Mon, 23 Sep 2024 10:30:32 -0700 Subject: [PATCH 19/41] Add READMEs for LeetCode and Redis --- LeetCode/README.md | 5 +++++ Redis/README.md | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 LeetCode/README.md create mode 100644 Redis/README.md diff --git a/LeetCode/README.md b/LeetCode/README.md new file mode 100644 index 0000000..24c81be --- /dev/null +++ b/LeetCode/README.md @@ -0,0 +1,5 @@ +# LeetCode Example + +In this example, Benchify debugs a faulty implementation of an edit distance algorithm (based on dynamic programming) for a LeetCode problem. This is a simple example meant for demos and presentations. + +Read the report [here](https://github.com/Benchify/benchify-examples/pull/76). diff --git a/Redis/README.md b/Redis/README.md new file mode 100644 index 0000000..88c602e --- /dev/null +++ b/Redis/README.md @@ -0,0 +1,5 @@ +# Mocks for Redis + +This example illustrates how Benchify can be used to test code which uses Redis, by leveraging mocks. We're actively building out mocks for a number of popular services such as Redis, GCP, AWS, Supabase, etc. The code being tested here is fairly trivial and simply meant to illustrate that Benchify works on code which uses Redis. + +Read the report [here](https://github.com/Benchify/benchify-examples/pull/114). From d86f7877ace3c59a26ca168d90d2fceb43c5d25b Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Mon, 23 Sep 2024 10:33:54 -0700 Subject: [PATCH 20/41] improve READMEs --- PyTorch2Jax/README.md | 2 ++ README.md | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/PyTorch2Jax/README.md b/PyTorch2Jax/README.md index fff7df5..a945bca 100644 --- a/PyTorch2Jax/README.md +++ b/PyTorch2Jax/README.md @@ -3,3 +3,5 @@ This example illustrates how Benchify can be used to test the equivalence of two austensibly equivalent functions. In this case, the customer translated some code from PyTorch to Jax, and wanted to make sure that the two implementations were functionally equivalent. Thank you to [Nithin Santi](https://www.linkedin.com/in/nithinsonti/) for contributing this example! Read the report [here](https://github.com/maxvonhippel/benchify-examples/pull/20). We're working on formatting improvements, and will share updates on this thread as they ship. + +Note, to run this example you do need to add `jax` and `torch` back to the requirements.txt. We removed them because they take a long time to install and slow down other tests which we run more frequently. \ No newline at end of file diff --git a/README.md b/README.md index dc6ff12..d684f08 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ # Examples of Benchify in Action 🥷🏼 -This repository contains interesting examples of how customers use Benchify to analyze their code. If you have an interesting use-case for us, please let us know! \ No newline at end of file +This repository contains interesting examples of how customers use Benchify to analyze their code. If you have an interesting use-case for us, or an example of Benchify in action you'd like to share, please let us know! + +Note, these are just a small set of examples which we make public for customer conversations and investor meetings -- we have a very large corpus of private examples as well. If you receive a bug report from us on your open-source repository, and would like us to share the corresponding analysis here, let us know and we will add it with either a minimum viable reproducible example or a git submodule based integration. \ No newline at end of file From 88e73e7b826a1d47b566f72d218f87d4d1ad2e23 Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Thu, 9 Jan 2025 13:45:19 -0500 Subject: [PATCH 21/41] Began working on payroll cobol demo. --- COBOL/.gitignore | 1 + COBOL/README.md | 6 ++ COBOL/payroll.cbl | 50 ++++++++++++++++ COBOL/script.py | 142 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 199 insertions(+) create mode 100644 COBOL/.gitignore create mode 100644 COBOL/README.md create mode 100644 COBOL/payroll.cbl create mode 100644 COBOL/script.py diff --git a/COBOL/.gitignore b/COBOL/.gitignore new file mode 100644 index 0000000..40d88ad --- /dev/null +++ b/COBOL/.gitignore @@ -0,0 +1 @@ +payroll diff --git a/COBOL/README.md b/COBOL/README.md new file mode 100644 index 0000000..468d14d --- /dev/null +++ b/COBOL/README.md @@ -0,0 +1,6 @@ +# Code Modernization + +Astonishingly, 70% of all existing business logic is in COBOL, and 800 billion lines of COBOL are still in use in industry today [1]. +Many (perhaps all) companies that still use COBOL wish they could move off it, since it is massively antiquated and the only living engineers who still know it are in retirement homes. Obviously, LLMs present a compelling solution to this problem via automated translation. But how can you be sure the translation is correct? This demo is meant to illustrate how Benchify can fit into the analysis of a translation from COBOL to Python. + +[1]: https://cobolcowboys.com/cobol-today/#:~:text=70%25%20of%20all%20critical%20business,use%20today%20by%20various%20industries. \ No newline at end of file diff --git a/COBOL/payroll.cbl b/COBOL/payroll.cbl new file mode 100644 index 0000000..912e054 --- /dev/null +++ b/COBOL/payroll.cbl @@ -0,0 +1,50 @@ +IDENTIFICATION DIVISION. +PROGRAM-ID. PAYROLL. + +ENVIRONMENT DIVISION. +INPUT-OUTPUT SECTION. +FILE-CONTROL. + SELECT EMPLOYEE-FILE ASSIGN TO DYNAMIC-FILE-NAME + ORGANIZATION IS LINE SEQUENTIAL. + +DATA DIVISION. +FILE SECTION. + FD EMPLOYEE-FILE + LABEL RECORDS ARE STANDARD + BLOCK CONTAINS 0 RECORDS + DATA RECORD IS EMPLOYEE-RECORD. + 01 EMPLOYEE-RECORD. + 05 EMP-ID PIC 9(5). + 05 HOURS-WORKED PIC 9(3). + 05 HOURLY-RATE PIC 9(5)V99. + 05 TAX-DEDUCTION PIC 9(5)V99. + +WORKING-STORAGE SECTION. +01 GROSS-PAY PIC 9(7)V99. +01 NET-PAY PIC 9(7)V99. +01 END-OF-FILE PIC X VALUE SPACE. +01 DYNAMIC-FILE-NAME PIC X(100). +01 FILE-STATUS PIC XX. + +PROCEDURE DIVISION. + ACCEPT DYNAMIC-FILE-NAME FROM COMMAND-LINE. + + OPEN INPUT EMPLOYEE-FILE + IF FILE-STATUS NOT = "00" + DISPLAY "Error opening file: " DYNAMIC-FILE-NAME + STOP RUN + END-IF. + + DISPLAY "EMP-ID,GROSS-PAY,NET-PAY" + PERFORM UNTIL END-OF-FILE = "EOF" + READ EMPLOYEE-FILE INTO EMPLOYEE-RECORD + AT END MOVE "EOF" TO END-OF-FILE + NOT AT END + COMPUTE GROSS-PAY = HOURS-WORKED * HOURLY-RATE + COMPUTE NET-PAY = GROSS-PAY - TAX-DEDUCTION + DISPLAY EMP-ID "," GROSS-PAY "," NET-PAY + END-READ + END-PERFORM. + + CLOSE EMPLOYEE-FILE. + STOP RUN. diff --git a/COBOL/script.py b/COBOL/script.py new file mode 100644 index 0000000..a7ea990 --- /dev/null +++ b/COBOL/script.py @@ -0,0 +1,142 @@ +import subprocess +import csv +import shutil +import os +from dataclasses import dataclass +from typing import List, Tuple +import platform + +@dataclass +class EmployeeRecord: + emp_id: str + hours_worked: float + hourly_rate: float + tax_deduction: float + +def install_cobc_and_compile_script(): + """Installs GNU COBOL if it's not already installed.""" + if shutil.which("cobc") is None: + print("GNU COBOL (cobc) is not installed. Installing it now...") + try: + os_name = platform.system() + if os_name == "Linux": + distro = platform.linux_distribution()[0].lower() + if "ubuntu" in distro or "debian" in distro: + subprocess.run(["apt", "install", "-y", "gnucobol"], check=True) + elif "fedora" in distro or "centos" in distro: + subprocess.run(["dnf", "install", "-y", "gnucobol"], check=True) + elif "arch" in distro: + subprocess.run(["pacman", "-S", "--noconfirm", "gnucobol"], check=True) + else: + raise Exception("Unsupported Linux distribution. Please install GNU COBOL manually.") + elif os_name == "Darwin": # macOS + subprocess.run(["brew", "install", "gnucobol"], check=True) + elif os_name == "Windows": + raise Exception("Please install GNU COBOL manually on Windows.") + else: + raise Exception("Unsupported operating system. Please install GNU COBOL manually.") + except subprocess.CalledProcessError as e: + print("Failed to install GNU COBOL. Please install it manually.") + raise e + else: + print("GNU COBOL (cobc) is already installed.") + + if not os.path.exists("payroll.cbl"): + raise FileNotFoundError("The COBOL script 'payroll.cbl' was not found.") + + if not os.path.exists("payroll"): + print("Compiling payroll.cbl...") + compile_command = ["cobc", "-x", "-o", "payroll", "payroll.cbl"] + try: + subprocess.run(compile_command, check=True) + print("Compilation successful.") + except subprocess.CalledProcessError as e: + print("Error compiling COBOL script.") + raise e + else: + print("Using existing compiled payroll program.") + +def process_payroll_cobol(employee_records: List[EmployeeRecord]) -> List[Tuple[float, float]]: + """Compiles and runs the COBOL payroll script, then processes its output.""" + # Ensure GNU COBOL is installed + install_cobc_and_compile_script() + + # Create temporary input file with random name + temp_file = f"temp_payroll_input_{os.urandom(8).hex()}.csv" + with open(temp_file, 'w', newline='') as f: + writer = csv.writer(f) + writer.writerow(['EMP-ID', 'HOURS-WORKED', 'HOURLY-RATE', 'TAX-DEDUCTION']) + for record in employee_records: + writer.writerow([record.emp_id, record.hours_worked, record.hourly_rate, record.tax_deduction]) + + try: + # Run the compiled COBOL program with the input file name as an argument + print("Running the COBOL payroll program...") + run_command = ["./payroll", temp_file] + try: + result = subprocess.run(run_command, capture_output=True, text=True, check=True) + except subprocess.CalledProcessError as e: + print(f"Error running COBOL program. Exit code: {e.returncode}") + print(f"Command that failed: {' '.join(e.cmd)}") + print("Standard output:") + print(e.stdout if e.stdout else "") + print("Standard error:") + print(e.stderr if e.stderr else "") + print(f"Input file contents:") + with open(temp_file, 'r') as f: + print(f.read()) + raise e + + # Process the COBOL output + print("Processing COBOL output...") + output_lines = result.stdout.splitlines() + if not output_lines: + raise ValueError("COBOL program produced no output") + + reader = csv.DictReader(output_lines) + if not reader.fieldnames: + raise ValueError(f"Invalid CSV output format. Raw output:\n{result.stdout}") + + results = [] + for row in reader: + try: + emp_id = row["EMP-ID"] + gross_pay = float(row["GROSS-PAY"]) + net_pay = float(row["NET-PAY"]) + + # Display results + print(f"Employee ID: {emp_id}") + print(f"Gross Pay: ${gross_pay:.2f}") + print(f"Net Pay: ${net_pay:.2f}") + + # Append to results + results.append((gross_pay, net_pay)) + except KeyError as e: + raise ValueError(f"Missing required column in output: {e}. Available columns: {reader.fieldnames}") + except ValueError as e: + raise ValueError(f"Invalid number format in output for employee {emp_id}: {e}") + + return results + + finally: + # Clean up temporary file + if os.path.exists(temp_file): + os.remove(temp_file) + +# Modernized version of process_payroll_cobol. This is meant to produce exactly the same +# result, but in Python. +def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, float]]: + """Processes payroll directly using Python logic.""" + results = [] + for record in employee_records: + # Calculate gross pay and net pay + gross_pay = record.hours_worked * record.hourly_rate + net_pay = gross_pay - record.tax_deduction + + # Display results + print(f"Employee ID: {record.emp_id}") + print(f"Net Pay: ${net_pay:.2f}") + + results.append((gross_pay, net_pay)) + + return results \ No newline at end of file From ec0281a0766afb219c34ade939316b6659ba0b38 Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Thu, 9 Jan 2025 14:00:20 -0500 Subject: [PATCH 22/41] more gpt-suggested changes trying to get the cobol to run --- COBOL/.gitignore | 1 + COBOL/payroll.cbl | 14 ++-- COBOL/script.py | 169 +++++++++++++++++++++++++++------------------- 3 files changed, 110 insertions(+), 74 deletions(-) diff --git a/COBOL/.gitignore b/COBOL/.gitignore index 40d88ad..70bf083 100644 --- a/COBOL/.gitignore +++ b/COBOL/.gitignore @@ -1 +1,2 @@ payroll +*.txt diff --git a/COBOL/payroll.cbl b/COBOL/payroll.cbl index 912e054..473c10a 100644 --- a/COBOL/payroll.cbl +++ b/COBOL/payroll.cbl @@ -5,7 +5,8 @@ ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT EMPLOYEE-FILE ASSIGN TO DYNAMIC-FILE-NAME - ORGANIZATION IS LINE SEQUENTIAL. + ORGANIZATION IS LINE SEQUENTIAL + FILE STATUS IS FILE-STATUS. DATA DIVISION. FILE SECTION. @@ -14,7 +15,7 @@ FILE SECTION. BLOCK CONTAINS 0 RECORDS DATA RECORD IS EMPLOYEE-RECORD. 01 EMPLOYEE-RECORD. - 05 EMP-ID PIC 9(5). + 05 EMP-ID PIC X(5). 05 HOURS-WORKED PIC 9(3). 05 HOURLY-RATE PIC 9(5)V99. 05 TAX-DEDUCTION PIC 9(5)V99. @@ -30,16 +31,21 @@ PROCEDURE DIVISION. ACCEPT DYNAMIC-FILE-NAME FROM COMMAND-LINE. OPEN INPUT EMPLOYEE-FILE + DISPLAY "DEBUG: FILE-STATUS AFTER OPEN = " FILE-STATUS IF FILE-STATUS NOT = "00" DISPLAY "Error opening file: " DYNAMIC-FILE-NAME STOP RUN - END-IF. + END-IF DISPLAY "EMP-ID,GROSS-PAY,NET-PAY" PERFORM UNTIL END-OF-FILE = "EOF" READ EMPLOYEE-FILE INTO EMPLOYEE-RECORD - AT END MOVE "EOF" TO END-OF-FILE + AT END + MOVE "EOF" TO END-OF-FILE NOT AT END + *> Debug lines to ensure we see raw data + DISPLAY "DEBUG: Raw record read = [" EMP-ID HOURS-WORKED HOURLY-RATE TAX-DEDUCTION "]" + COMPUTE GROSS-PAY = HOURS-WORKED * HOURLY-RATE COMPUTE NET-PAY = GROSS-PAY - TAX-DEDUCTION DISPLAY EMP-ID "," GROSS-PAY "," NET-PAY diff --git a/COBOL/script.py b/COBOL/script.py index a7ea990..fde84c0 100644 --- a/COBOL/script.py +++ b/COBOL/script.py @@ -44,87 +44,115 @@ def install_cobc_and_compile_script(): if not os.path.exists("payroll.cbl"): raise FileNotFoundError("The COBOL script 'payroll.cbl' was not found.") - if not os.path.exists("payroll"): - print("Compiling payroll.cbl...") - compile_command = ["cobc", "-x", "-o", "payroll", "payroll.cbl"] - try: - subprocess.run(compile_command, check=True) - print("Compilation successful.") - except subprocess.CalledProcessError as e: - print("Error compiling COBOL script.") - raise e - else: - print("Using existing compiled payroll program.") + # Always recompile to ensure we have the latest version + if os.path.exists("payroll"): + os.remove("payroll") + print("Compiling payroll.cbl...") + compile_command = ["cobc", "-x", "-o", "payroll", "payroll.cbl"] + try: + subprocess.run(compile_command, check=True) + print("Compilation successful.") + except subprocess.CalledProcessError as e: + print("Error compiling COBOL script.") + raise e + +def format_pic_9_5_v_99(num: float) -> str: + """ + For PIC 9(5)V99, we need 7 numeric digits total, with an implied + decimal point before the last two digits. Example: + 20.0 -> 20.00 -> multiply by 100 = 2000 -> zero-pad to 7 -> "0002000" + """ + # Multiply by 100, round, then zero-pad to length=7 + value_as_int = int(round(num * 100)) + return f"{value_as_int:07d}" def process_payroll_cobol(employee_records: List[EmployeeRecord]) -> List[Tuple[float, float]]: """Compiles and runs the COBOL payroll script, then processes its output.""" - # Ensure GNU COBOL is installed + + # 1) Ensure GNU COBOL is installed & compile the COBOL code install_cobc_and_compile_script() - # Create temporary input file with random name - temp_file = f"temp_payroll_input_{os.urandom(8).hex()}.csv" + # 2) Create a temporary input file with random name + temp_file = f"temp_payroll_input_{os.urandom(8).hex()}.txt" + + # 3) Write data in the fixed-length format + print("=== Debug: Writing the following lines to input file ===") with open(temp_file, 'w', newline='') as f: - writer = csv.writer(f) - writer.writerow(['EMP-ID', 'HOURS-WORKED', 'HOURLY-RATE', 'TAX-DEDUCTION']) for record in employee_records: - writer.writerow([record.emp_id, record.hours_worked, record.hourly_rate, record.tax_deduction]) + # EMP-ID: 5 chars + emp_id_str = record.emp_id[:5].ljust(5) + + # HOURS: 3 digits + hours_str = f"{int(record.hours_worked):03d}" + + # HOURLY-RATE: 7 digits + hourly_rate_str = format_pic_9_5_v_99(record.hourly_rate) + + # TAX-DEDUCTION: 7 digits + tax_deduction_str = format_pic_9_5_v_99(record.tax_deduction) + + line = emp_id_str + hours_str + hourly_rate_str + tax_deduction_str + print(line) # Print for debug + f.write(line + "\n") + print("=======================================================") + + # 4) Run the compiled COBOL program with the input file as an argument + print(f"Running the COBOL payroll program with file: {temp_file}") + run_command = ["./payroll", temp_file] try: - # Run the compiled COBOL program with the input file name as an argument - print("Running the COBOL payroll program...") - run_command = ["./payroll", temp_file] - try: - result = subprocess.run(run_command, capture_output=True, text=True, check=True) - except subprocess.CalledProcessError as e: - print(f"Error running COBOL program. Exit code: {e.returncode}") - print(f"Command that failed: {' '.join(e.cmd)}") - print("Standard output:") - print(e.stdout if e.stdout else "") - print("Standard error:") - print(e.stderr if e.stderr else "") - print(f"Input file contents:") - with open(temp_file, 'r') as f: - print(f.read()) - raise e + result = subprocess.run(run_command, capture_output=True, text=True, check=True) + except subprocess.CalledProcessError as e: + print(f"Error running COBOL program. Exit code: {e.returncode}") + print(f"Command that failed: {' '.join(e.cmd)}") + print("=== Standard output ===") + print(e.stdout if e.stdout else "") + print("=== Standard error ===") + print(e.stderr if e.stderr else "") + print("=== Input file contents ===") + with open(temp_file, 'r') as input_f: + print(input_f.read()) + raise e + + # 5) Process the COBOL output + print("Processing COBOL output...") + output_lines = result.stdout.splitlines() + if not output_lines: + print("=== No output from COBOL ===") + return [] - # Process the COBOL output - print("Processing COBOL output...") - output_lines = result.stdout.splitlines() - if not output_lines: - raise ValueError("COBOL program produced no output") + print("=== Raw COBOL Output ===") + for line in output_lines: + print(line) + print("=========================") + + # The first line should be: "EMP-ID,GROSS-PAY,NET-PAY" + reader = csv.DictReader(output_lines) + if not reader.fieldnames or "EMP-ID" not in reader.fieldnames: + print(f"=== Invalid CSV output format ===\n{result.stdout}") + return [] + + results = [] + for row in reader: + try: + emp_id = row["EMP-ID"] + gross_pay = float(row["GROSS-PAY"]) + net_pay = float(row["NET-PAY"]) - reader = csv.DictReader(output_lines) - if not reader.fieldnames: - raise ValueError(f"Invalid CSV output format. Raw output:\n{result.stdout}") - - results = [] - for row in reader: - try: - emp_id = row["EMP-ID"] - gross_pay = float(row["GROSS-PAY"]) - net_pay = float(row["NET-PAY"]) - - # Display results - print(f"Employee ID: {emp_id}") - print(f"Gross Pay: ${gross_pay:.2f}") - print(f"Net Pay: ${net_pay:.2f}") - - # Append to results - results.append((gross_pay, net_pay)) - except KeyError as e: - raise ValueError(f"Missing required column in output: {e}. Available columns: {reader.fieldnames}") - except ValueError as e: - raise ValueError(f"Invalid number format in output for employee {emp_id}: {e}") - - return results + # Debug prints + print(f"Employee ID: {emp_id}") + print(f"Gross Pay: {gross_pay:.2f}") + print(f"Net Pay: {net_pay:.2f}") + results.append((gross_pay, net_pay)) + except KeyError as e: + print(f"Missing required column in output: {e}. Available columns: {reader.fieldnames}") + except ValueError as e: + print(f"Invalid number format in output for employee {emp_id}: {e}") - finally: - # Clean up temporary file - if os.path.exists(temp_file): - os.remove(temp_file) + return results -# Modernized version of process_payroll_cobol. This is meant to produce exactly the same -# result, but in Python. +# Modernized version of process_payroll_cobol. This is meant to produce exactly +# the same result, but in Python. def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, float]]: """Processes payroll directly using Python logic.""" results = [] @@ -135,8 +163,9 @@ def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, # Display results print(f"Employee ID: {record.emp_id}") - print(f"Net Pay: ${net_pay:.2f}") + print(f"Gross Pay: ${gross_pay:.2f}") + print(f"Net Pay: ${net_pay:.2f}") results.append((gross_pay, net_pay)) - return results \ No newline at end of file + return results From ff846fed1afb9833c9356c214e9b5c6dd35dedf1 Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Thu, 9 Jan 2025 14:15:14 -0500 Subject: [PATCH 23/41] Getting closer, but currently running into: ./payroll temp_payroll_input_7ccdb2f020a63a7f.txt libcob: error: module 'C$GETARG' not found so need to fix this. --- COBOL/payroll.cbl | 124 +++++++++++++++++++++++++--------------------- 1 file changed, 68 insertions(+), 56 deletions(-) diff --git a/COBOL/payroll.cbl b/COBOL/payroll.cbl index 473c10a..c762994 100644 --- a/COBOL/payroll.cbl +++ b/COBOL/payroll.cbl @@ -1,56 +1,68 @@ -IDENTIFICATION DIVISION. -PROGRAM-ID. PAYROLL. - -ENVIRONMENT DIVISION. -INPUT-OUTPUT SECTION. -FILE-CONTROL. - SELECT EMPLOYEE-FILE ASSIGN TO DYNAMIC-FILE-NAME - ORGANIZATION IS LINE SEQUENTIAL - FILE STATUS IS FILE-STATUS. - -DATA DIVISION. -FILE SECTION. - FD EMPLOYEE-FILE - LABEL RECORDS ARE STANDARD - BLOCK CONTAINS 0 RECORDS - DATA RECORD IS EMPLOYEE-RECORD. - 01 EMPLOYEE-RECORD. - 05 EMP-ID PIC X(5). - 05 HOURS-WORKED PIC 9(3). - 05 HOURLY-RATE PIC 9(5)V99. - 05 TAX-DEDUCTION PIC 9(5)V99. - -WORKING-STORAGE SECTION. -01 GROSS-PAY PIC 9(7)V99. -01 NET-PAY PIC 9(7)V99. -01 END-OF-FILE PIC X VALUE SPACE. -01 DYNAMIC-FILE-NAME PIC X(100). -01 FILE-STATUS PIC XX. - -PROCEDURE DIVISION. - ACCEPT DYNAMIC-FILE-NAME FROM COMMAND-LINE. - - OPEN INPUT EMPLOYEE-FILE - DISPLAY "DEBUG: FILE-STATUS AFTER OPEN = " FILE-STATUS - IF FILE-STATUS NOT = "00" - DISPLAY "Error opening file: " DYNAMIC-FILE-NAME - STOP RUN - END-IF - - DISPLAY "EMP-ID,GROSS-PAY,NET-PAY" - PERFORM UNTIL END-OF-FILE = "EOF" - READ EMPLOYEE-FILE INTO EMPLOYEE-RECORD - AT END - MOVE "EOF" TO END-OF-FILE - NOT AT END - *> Debug lines to ensure we see raw data - DISPLAY "DEBUG: Raw record read = [" EMP-ID HOURS-WORKED HOURLY-RATE TAX-DEDUCTION "]" - - COMPUTE GROSS-PAY = HOURS-WORKED * HOURLY-RATE - COMPUTE NET-PAY = GROSS-PAY - TAX-DEDUCTION - DISPLAY EMP-ID "," GROSS-PAY "," NET-PAY - END-READ - END-PERFORM. - - CLOSE EMPLOYEE-FILE. - STOP RUN. + $set sourceformat"free" + IDENTIFICATION DIVISION. + PROGRAM-ID. PAYROLL. + + ENVIRONMENT DIVISION. + INPUT-OUTPUT SECTION. + FILE-CONTROL. + SELECT EMPLOYEE-FILE ASSIGN TO DYNAMIC-FILE-NAME + ORGANIZATION IS LINE SEQUENTIAL + FILE STATUS IS FILE-STATUS. + + DATA DIVISION. + FILE SECTION. + FD EMPLOYEE-FILE + LABEL RECORDS ARE STANDARD + BLOCK CONTAINS 0 RECORDS + DATA RECORD IS EMPLOYEE-RECORD. + 01 EMPLOYEE-RECORD. + 05 EMP-ID PIC X(5). + 05 HOURS-WORKED PIC 9(3). + 05 HOURLY-RATE PIC 9(5)V99. + 05 TAX-DEDUCTION PIC 9(5)V99. + + WORKING-STORAGE SECTION. + 01 GROSS-PAY PIC 9(7)V99. + 01 NET-PAY PIC 9(7)V99. + 01 END-OF-FILE PIC X VALUE SPACE. + 01 DYNAMIC-FILE-NAME PIC X(100). + 01 FILE-STATUS PIC XX. + + PROCEDURE DIVISION. + + *> Retrieve the first argument with C$GETARG + CALL "C$GETARG" USING + BY VALUE 1 + BY REFERENCE DYNAMIC-FILE-NAME + *> Debug: see what we got + DISPLAY "DEBUG: DYNAMIC-FILE-NAME = [" DYNAMIC-FILE-NAME "]" + + *> Now open the file using DYNAMIC-FILE-NAME + OPEN INPUT EMPLOYEE-FILE + DISPLAY "DEBUG: FILE-STATUS AFTER OPEN = " FILE-STATUS + IF FILE-STATUS NOT = "00" + DISPLAY "Error opening file: " DYNAMIC-FILE-NAME + STOP RUN + END-IF + + *> Output CSV Header + DISPLAY "EMP-ID,GROSS-PAY,NET-PAY" + + *> Read until EOF + PERFORM UNTIL END-OF-FILE = "EOF" + READ EMPLOYEE-FILE INTO EMPLOYEE-RECORD + AT END + MOVE "EOF" TO END-OF-FILE + NOT AT END + *> Debug: Show raw data + DISPLAY "DEBUG: Raw record read = [" + EMP-ID HOURS-WORKED HOURLY-RATE TAX-DEDUCTION "]" + + COMPUTE GROSS-PAY = HOURS-WORKED * HOURLY-RATE + COMPUTE NET-PAY = GROSS-PAY - TAX-DEDUCTION + DISPLAY EMP-ID "," GROSS-PAY "," NET-PAY + END-READ + END-PERFORM + + CLOSE EMPLOYEE-FILE + STOP RUN. From d162136a7360cf310dbcaf99afd78ff27d89e958 Mon Sep 17 00:00:00 2001 From: vinkabuki Date: Thu, 9 Jan 2025 21:37:38 +0100 Subject: [PATCH 24/41] Cobol code is now running but it returns malformed output: DEBUG: Raw record read = [E001 04000025.0000100.00] E001 ,0001000.00,0000900.00 DEBUG: Raw record read = [E002 03500030.0000150.00] E002 ,0001050.00,0000900.00 DEBUG: Raw record read = [E003 04500020.0000090.00] E003 ,0000900.00,0000810.00 DEBUG: Raw record read = [E004 05000022.5000120.00] E004 ,0001125.00,0001005.00 --- COBOL/payroll.cbl | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/COBOL/payroll.cbl b/COBOL/payroll.cbl index c762994..ad5cb9b 100644 --- a/COBOL/payroll.cbl +++ b/COBOL/payroll.cbl @@ -24,17 +24,14 @@ WORKING-STORAGE SECTION. 01 GROSS-PAY PIC 9(7)V99. 01 NET-PAY PIC 9(7)V99. - 01 END-OF-FILE PIC X VALUE SPACE. + 01 END-OF-FILE PIC X(3) VALUE SPACES. 01 DYNAMIC-FILE-NAME PIC X(100). 01 FILE-STATUS PIC XX. PROCEDURE DIVISION. - *> Retrieve the first argument with C$GETARG - CALL "C$GETARG" USING - BY VALUE 1 - BY REFERENCE DYNAMIC-FILE-NAME - *> Debug: see what we got + *> Retrieve the first argument using COMMAND-LINE + ACCEPT DYNAMIC-FILE-NAME FROM COMMAND-LINE DISPLAY "DEBUG: DYNAMIC-FILE-NAME = [" DYNAMIC-FILE-NAME "]" *> Now open the file using DYNAMIC-FILE-NAME From a27aa9cb3a7c9132836aa6682a8393bf10018af8 Mon Sep 17 00:00:00 2001 From: vinkabuki Date: Thu, 9 Jan 2025 21:50:48 +0100 Subject: [PATCH 25/41] Removed debug logs from COBOL code. Python and Cobol outputs are now the same. --- COBOL/payroll.cbl | 6 ------ COBOL/script.py | 4 ++-- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/COBOL/payroll.cbl b/COBOL/payroll.cbl index ad5cb9b..25f531c 100644 --- a/COBOL/payroll.cbl +++ b/COBOL/payroll.cbl @@ -32,11 +32,9 @@ *> Retrieve the first argument using COMMAND-LINE ACCEPT DYNAMIC-FILE-NAME FROM COMMAND-LINE - DISPLAY "DEBUG: DYNAMIC-FILE-NAME = [" DYNAMIC-FILE-NAME "]" *> Now open the file using DYNAMIC-FILE-NAME OPEN INPUT EMPLOYEE-FILE - DISPLAY "DEBUG: FILE-STATUS AFTER OPEN = " FILE-STATUS IF FILE-STATUS NOT = "00" DISPLAY "Error opening file: " DYNAMIC-FILE-NAME STOP RUN @@ -51,10 +49,6 @@ AT END MOVE "EOF" TO END-OF-FILE NOT AT END - *> Debug: Show raw data - DISPLAY "DEBUG: Raw record read = [" - EMP-ID HOURS-WORKED HOURLY-RATE TAX-DEDUCTION "]" - COMPUTE GROSS-PAY = HOURS-WORKED * HOURLY-RATE COMPUTE NET-PAY = GROSS-PAY - TAX-DEDUCTION DISPLAY EMP-ID "," GROSS-PAY "," NET-PAY diff --git a/COBOL/script.py b/COBOL/script.py index fde84c0..7044845 100644 --- a/COBOL/script.py +++ b/COBOL/script.py @@ -141,8 +141,8 @@ def process_payroll_cobol(employee_records: List[EmployeeRecord]) -> List[Tuple[ # Debug prints print(f"Employee ID: {emp_id}") - print(f"Gross Pay: {gross_pay:.2f}") - print(f"Net Pay: {net_pay:.2f}") + print(f"Gross Pay: ${gross_pay:.2f}") + print(f"Net Pay: ${net_pay:.2f}") results.append((gross_pay, net_pay)) except KeyError as e: print(f"Missing required column in output: {e}. Available columns: {reader.fieldnames}") From 3df4c73fa13f698ecb1a28dbde09f6d47c966455 Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Thu, 9 Jan 2025 17:34:15 -0700 Subject: [PATCH 26/41] Better docstrings. --- COBOL/README.md | 68 ++++++++++++++++++++++++++++++++++++++++++ COBOL/script.py | 79 +++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 138 insertions(+), 9 deletions(-) diff --git a/COBOL/README.md b/COBOL/README.md index 468d14d..cef3b47 100644 --- a/COBOL/README.md +++ b/COBOL/README.md @@ -3,4 +3,72 @@ Astonishingly, 70% of all existing business logic is in COBOL, and 800 billion lines of COBOL are still in use in industry today [1]. Many (perhaps all) companies that still use COBOL wish they could move off it, since it is massively antiquated and the only living engineers who still know it are in retirement homes. Obviously, LLMs present a compelling solution to this problem via automated translation. But how can you be sure the translation is correct? This demo is meant to illustrate how Benchify can fit into the analysis of a translation from COBOL to Python. +Example usage: +``` +ipython3 +Python 3.9.6 (default, Nov 11 2024, 03:15:38) +Type 'copyright', 'credits' or 'license' for more information +IPython 8.18.1 -- An enhanced Interactive Python. Type '?' for help. + +In [1]: from script import * + ...: install_cobc_and_compile_script() + ...: + ...: employee_records = [ + ...: EmployeeRecord(emp_id="12345", hours_worked=40, hourly_rate=20.0, tax_deduction=50.0), + ...: EmployeeRecord(emp_id="67890", hours_worked=35, hourly_rate=15.0, tax_deduction=30.0), + ...: EmployeeRecord(emp_id="54321", hours_worked=45, hourly_rate=25.0, tax_deduction=70.0) + ...: ] + ...: + ...: payroll_results = process_payroll_cobol(employee_records) + ...: payroll_results +GNU COBOL (cobc) is already installed. +Compiling payroll.cbl... +Compilation successful. +GNU COBOL (cobc) is already installed. +Compiling payroll.cbl... +Compilation successful. +=== Debug: Writing the following lines to input file === +1234504000020000005000 +6789003500015000003000 +5432104500025000007000 +======================================================= +Running the COBOL payroll program with file: temp_payroll_input_ceacb40a807b19a0.txt +Processing COBOL output... +=== Raw COBOL Output === +EMP-ID,GROSS-PAY,NET-PAY +12345,0000800.00,0000750.00 +67890,0000525.00,0000495.00 +54321,0001125.00,0001055.00 +========================= +Employee ID: 12345 +Gross Pay: $800.00 +Net Pay: $750.00 +Employee ID: 67890 +Gross Pay: $525.00 +Net Pay: $495.00 +Employee ID: 54321 +Gross Pay: $1125.00 +Net Pay: $1055.00 +Out[1]: [(800.0, 750.0), (525.0, 495.0), (1125.0, 1055.0)] + +In [2]: payroll_results_2 = process_payroll(employee_records) +Employee ID: 12345 +Gross Pay: $800.00 +Net Pay: $750.00 +Employee ID: 67890 +Gross Pay: $525.00 +Net Pay: $495.00 +Employee ID: 54321 +Gross Pay: $1125.00 +Net Pay: $1055.00 + +In [3]: payroll_results_2 +Out[3]: [(800.0, 750.0), (525.0, 495.0), (1125.0, 1055.0)] + +In [4]: payroll_results_2 == payroll_results +Out[4]: True + +In [5]: exit() +``` + [1]: https://cobolcowboys.com/cobol-today/#:~:text=70%25%20of%20all%20critical%20business,use%20today%20by%20various%20industries. \ No newline at end of file diff --git a/COBOL/script.py b/COBOL/script.py index 7044845..78dd24e 100644 --- a/COBOL/script.py +++ b/COBOL/script.py @@ -8,13 +8,34 @@ @dataclass class EmployeeRecord: + """ + Data class representing an employee's payroll record. + + Attributes: + emp_id: Employee ID string + hours_worked: Number of hours worked in pay period + hourly_rate: Pay rate per hour + tax_deduction: Amount to deduct for taxes + """ emp_id: str hours_worked: float hourly_rate: float tax_deduction: float def install_cobc_and_compile_script(): - """Installs GNU COBOL if it's not already installed.""" + """ + Installs GNU COBOL compiler if not present and compiles the COBOL payroll script. + + This function: + 1. Checks if cobc compiler is installed + 2. If not installed, attempts to install it using the appropriate package manager + 3. Compiles payroll.cbl into an executable + + Raises: + FileNotFoundError: If payroll.cbl is missing + subprocess.CalledProcessError: If installation or compilation fails + Exception: If on an unsupported OS or Linux distribution + """ if shutil.which("cobc") is None: print("GNU COBOL (cobc) is not installed. Installing it now...") try: @@ -58,17 +79,44 @@ def install_cobc_and_compile_script(): def format_pic_9_5_v_99(num: float) -> str: """ - For PIC 9(5)V99, we need 7 numeric digits total, with an implied - decimal point before the last two digits. Example: - 20.0 -> 20.00 -> multiply by 100 = 2000 -> zero-pad to 7 -> "0002000" + Formats a number according to COBOL's PIC 9(5)V99 format specification. + + This creates a 7-digit string where the last 2 digits represent decimal places. + The decimal point is implied (not actually present in output). + + Args: + num: The float number to format + + Returns: + A 7-character string with leading zeros + + Example: + 20.0 -> "0002000" (represents 20.00) + 15.50 -> "0001550" (represents 15.50) """ # Multiply by 100, round, then zero-pad to length=7 value_as_int = int(round(num * 100)) return f"{value_as_int:07d}" def process_payroll_cobol(employee_records: List[EmployeeRecord]) -> List[Tuple[float, float]]: - """Compiles and runs the COBOL payroll script, then processes its output.""" - + """ + Processes payroll by running a COBOL program and parsing its output. + + This function: + 1. Ensures COBOL compiler is installed + 2. Creates a temporary input file with employee data + 3. Runs the COBOL payroll program + 4. Parses the CSV output to extract gross and net pay + + Args: + employee_records: List of EmployeeRecord objects containing payroll data + + Returns: + List of tuples containing (gross_pay, net_pay) for each employee + + Raises: + Various exceptions from subprocess calls and file operations + """ # 1) Ensure GNU COBOL is installed & compile the COBOL code install_cobc_and_compile_script() @@ -151,10 +199,23 @@ def process_payroll_cobol(employee_records: List[EmployeeRecord]) -> List[Tuple[ return results -# Modernized version of process_payroll_cobol. This is meant to produce exactly -# the same result, but in Python. def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, float]]: - """Processes payroll directly using Python logic.""" + """ + Pure Python implementation of the COBOL payroll processing logic. + + This function performs the same calculations as the COBOL program but in Python. + It should perform the exact same result as process_payroll_cobol on all possible inputs, + and throw the same exceptions in the same scenarios. + + Args: + employee_records: List of EmployeeRecord objects containing payroll data + + Returns: + List of tuples containing (gross_pay, net_pay) for each employee + + Note: + Results should exactly match process_payroll_cobol() output + """ results = [] for record in employee_records: # Calculate gross pay and net pay From f646a85c40e5b2604ace347ccae6879c3b1c9d09 Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Thu, 9 Jan 2025 18:57:40 -0700 Subject: [PATCH 27/41] improve comments --- COBOL/script.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/COBOL/script.py b/COBOL/script.py index 78dd24e..b681555 100644 --- a/COBOL/script.py +++ b/COBOL/script.py @@ -94,6 +94,7 @@ def format_pic_9_5_v_99(num: float) -> str: 20.0 -> "0002000" (represents 20.00) 15.50 -> "0001550" (represents 15.50) """ + # Multiply by 100, round, then zero-pad to length=7 value_as_int = int(round(num * 100)) return f"{value_as_int:07d}" @@ -213,9 +214,11 @@ def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, Returns: List of tuples containing (gross_pay, net_pay) for each employee - Note: - Results should exactly match process_payroll_cobol() output + PROPERTY: + Results should exactly match process_payroll_cobol() output. + IE, for all ers: List[EmployeeRecord], process_payroll(er) == process_payroll_cobol(er) """ + results = [] for record in employee_records: # Calculate gross pay and net pay From 7ac48b426d64f27c512d10e1f2d94bb3a32b8d68 Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Fri, 10 Jan 2025 08:50:06 -0700 Subject: [PATCH 28/41] Fix overflow error. --- COBOL/script.py | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/COBOL/script.py b/COBOL/script.py index b681555..2f315a6 100644 --- a/COBOL/script.py +++ b/COBOL/script.py @@ -5,6 +5,7 @@ from dataclasses import dataclass from typing import List, Tuple import platform +import math @dataclass class EmployeeRecord: @@ -93,11 +94,27 @@ def format_pic_9_5_v_99(num: float) -> str: Example: 20.0 -> "0002000" (represents 20.00) 15.50 -> "0001550" (represents 15.50) - """ + + Raises: + ValueError: If num is NaN, Inf, -Inf, or would result in a number too large + to represent in PIC 9(5)V99 format + """ + if math.isnan(num): + raise ValueError("Input cannot be NaN") + + if math.isinf(num): + raise ValueError("Input cannot be infinite") + + # Check range - PIC 9(5)V99 can only handle 0 to 99999.99 + if num < 0 or num > 99999.99: + raise ValueError("Number out of range for PIC 9(5)V99 format (0 to 99999.99)") - # Multiply by 100, round, then zero-pad to length=7 - value_as_int = int(round(num * 100)) - return f"{value_as_int:07d}" + try: + # Multiply by 100, round, then zero-pad to length=7 + value_as_int = int(round(num * 100)) + return f"{value_as_int:07d}" + except OverflowError: + raise ValueError("Number too large to represent in PIC 9(5)V99 format") def process_payroll_cobol(employee_records: List[EmployeeRecord]) -> List[Tuple[float, float]]: """ @@ -217,8 +234,8 @@ def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, PROPERTY: Results should exactly match process_payroll_cobol() output. IE, for all ers: List[EmployeeRecord], process_payroll(er) == process_payroll_cobol(er) - """ + """ results = [] for record in employee_records: # Calculate gross pay and net pay From 9bcb761164398d094537e2830428b2fc78fb22b6 Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Fri, 10 Jan 2025 09:35:57 -0700 Subject: [PATCH 29/41] Comment with desired property --- COBOL/script.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/COBOL/script.py b/COBOL/script.py index 2f315a6..682a3a7 100644 --- a/COBOL/script.py +++ b/COBOL/script.py @@ -19,9 +19,9 @@ class EmployeeRecord: tax_deduction: Amount to deduct for taxes """ emp_id: str - hours_worked: float - hourly_rate: float - tax_deduction: float + hours_worked: float # cannot be an inf or NaN + hourly_rate: float # cannot be an inf or NaN + tax_deduction: float # cannot be an inf or NaN def install_cobc_and_compile_script(): """ @@ -217,7 +217,7 @@ def process_payroll_cobol(employee_records: List[EmployeeRecord]) -> List[Tuple[ return results -def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, float]]: +def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, float]]: """ Pure Python implementation of the COBOL payroll processing logic. @@ -232,9 +232,10 @@ def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, List of tuples containing (gross_pay, net_pay) for each employee PROPERTY: - Results should exactly match process_payroll_cobol() output. - IE, for all ers: List[EmployeeRecord], process_payroll(er) == process_payroll_cobol(er) - + Results should exactly match process_payroll_cobol() output, including thrown exceptions. + IE, for all ers: List[EmployeeRecord], process_payroll(er) == process_payroll_cobol(er), + unless either side throws an Exception, in which case the other side should throw an identical + exception. """ results = [] for record in employee_records: @@ -249,4 +250,4 @@ def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, results.append((gross_pay, net_pay)) - return results + return results # should return the same result as process_payroll_cobol(employee_records) From e1316396f766c43b3b20c4b36decb69d7c30857b Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Fri, 10 Jan 2025 09:42:14 -0700 Subject: [PATCH 30/41] Fix cobol installation --- COBOL/script.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/COBOL/script.py b/COBOL/script.py index 682a3a7..bfa0a7d 100644 --- a/COBOL/script.py +++ b/COBOL/script.py @@ -42,7 +42,10 @@ def install_cobc_and_compile_script(): try: os_name = platform.system() if os_name == "Linux": - distro = platform.linux_distribution()[0].lower() + try: + distro = platform.linux_distribution()[0].lower() + except AttributeError: + distro = "ubuntu" if "ubuntu" in distro or "debian" in distro: subprocess.run(["apt", "install", "-y", "gnucobol"], check=True) elif "fedora" in distro or "centos" in distro: @@ -78,6 +81,8 @@ def install_cobc_and_compile_script(): print("Error compiling COBOL script.") raise e +install_cobc_and_compile_script() + def format_pic_9_5_v_99(num: float) -> str: """ Formats a number according to COBOL's PIC 9(5)V99 format specification. From fbc8a073a9ffe0e6d2100e56ea742c719a00f385 Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Fri, 10 Jan 2025 09:43:35 -0700 Subject: [PATCH 31/41] Fix error handling and add property --- COBOL/script.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/COBOL/script.py b/COBOL/script.py index bfa0a7d..ccc26ab 100644 --- a/COBOL/script.py +++ b/COBOL/script.py @@ -222,7 +222,7 @@ def process_payroll_cobol(employee_records: List[EmployeeRecord]) -> List[Tuple[ return results -def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, float]]: +def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, float]]: """ Pure Python implementation of the COBOL payroll processing logic. @@ -236,14 +236,15 @@ def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, Returns: List of tuples containing (gross_pay, net_pay) for each employee - PROPERTY: - Results should exactly match process_payroll_cobol() output, including thrown exceptions. - IE, for all ers: List[EmployeeRecord], process_payroll(er) == process_payroll_cobol(er), - unless either side throws an Exception, in which case the other side should throw an identical - exception. + TEST THIS PROPERTY: + Results should exactly match process_payroll_cobol() output, including thrown exceptions. + IE, for all ers: List[EmployeeRecord], process_payroll(er) == process_payroll_cobol(er), + unless either side throws an Exception, in which case the other side should throw an identical + exception. """ results = [] for record in employee_records: + # Calculate gross pay and net pay gross_pay = record.hours_worked * record.hourly_rate net_pay = gross_pay - record.tax_deduction @@ -255,4 +256,4 @@ def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, results.append((gross_pay, net_pay)) - return results # should return the same result as process_payroll_cobol(employee_records) + return results # this should return the same result as process_payroll_cobol(employee_records) From 20c5fe04b8309dac798ff986f8fa648fb1ab176b Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Fri, 10 Jan 2025 09:50:11 -0700 Subject: [PATCH 32/41] Initiate review of cobol->python translation --- COBOL/script.py | 66 ++++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 34 deletions(-) diff --git a/COBOL/script.py b/COBOL/script.py index ccc26ab..8e7bf0a 100644 --- a/COBOL/script.py +++ b/COBOL/script.py @@ -8,7 +8,7 @@ import math @dataclass -class EmployeeRecord: +class EmployeeRecord: # Class for EmployeeRecords """ Data class representing an employee's payroll record. @@ -83,7 +83,7 @@ def install_cobc_and_compile_script(): install_cobc_and_compile_script() -def format_pic_9_5_v_99(num: float) -> str: +def format_pic_9_5_v_99(num: float) -> str: # Function to format data for cobol ingestion """ Formats a number according to COBOL's PIC 9(5)V99 format specification. @@ -222,38 +222,36 @@ def process_payroll_cobol(employee_records: List[EmployeeRecord]) -> List[Tuple[ return results -def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, float]]: - """ - Pure Python implementation of the COBOL payroll processing logic. - - This function performs the same calculations as the COBOL program but in Python. - It should perform the exact same result as process_payroll_cobol on all possible inputs, - and throw the same exceptions in the same scenarios. - - Args: - employee_records: List of EmployeeRecord objects containing payroll data - - Returns: - List of tuples containing (gross_pay, net_pay) for each employee - - TEST THIS PROPERTY: - Results should exactly match process_payroll_cobol() output, including thrown exceptions. - IE, for all ers: List[EmployeeRecord], process_payroll(er) == process_payroll_cobol(er), - unless either side throws an Exception, in which case the other side should throw an identical - exception. +def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, float]]: # Python translation of cobol code + """ + Pure Python implementation of the COBOL payroll processing logic. + + This function performs the same calculations as the COBOL program but in Python. + It should perform the exact same result as process_payroll_cobol on all possible inputs, + and throw the same exceptions in the same scenarios. + + Args: + employee_records: List of EmployeeRecord objects containing payroll data + + Returns: + List of tuples containing (gross_pay, net_pay) for each employee + + TEST THIS PROPERTY: + Results should exactly match process_payroll_cobol() output, including thrown exceptions. + IE, for all ers: List[EmployeeRecord], process_payroll(er) == process_payroll_cobol(er), + unless either side throws an Exception, in which case the other side should throw an identical + exception. """ - results = [] - for record in employee_records: - - # Calculate gross pay and net pay - gross_pay = record.hours_worked * record.hourly_rate - net_pay = gross_pay - record.tax_deduction + results = [] + for record in employee_records: + # Calculate gross pay and net pay + gross_pay = record.hours_worked * record.hourly_rate + net_pay = gross_pay - record.tax_deduction - # Display results - print(f"Employee ID: {record.emp_id}") - print(f"Gross Pay: ${gross_pay:.2f}") - print(f"Net Pay: ${net_pay:.2f}") - - results.append((gross_pay, net_pay)) + # Display results + print(f"Employee ID: {record.emp_id}") + print(f"Gross Pay: ${gross_pay:.2f}") + print(f"Net Pay: ${net_pay:.2f}") + results.append((gross_pay, net_pay)) - return results # this should return the same result as process_payroll_cobol(employee_records) + return results # this SHOULD return the same result as process_payroll_cobol(employee_records) From 50c36f16a49ea4c0e9c27fc03afc07b14f7fca21 Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Fri, 10 Jan 2025 09:54:54 -0700 Subject: [PATCH 33/41] Fix issue with absolute path --- COBOL/script.py | 75 +++++++++++++++++++++++++------------------------ 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/COBOL/script.py b/COBOL/script.py index 8e7bf0a..413fbe5 100644 --- a/COBOL/script.py +++ b/COBOL/script.py @@ -66,14 +66,19 @@ def install_cobc_and_compile_script(): else: print("GNU COBOL (cobc) is already installed.") - if not os.path.exists("payroll.cbl"): - raise FileNotFoundError("The COBOL script 'payroll.cbl' was not found.") + # Get the directory where this script resides + script_dir = os.path.dirname(os.path.abspath(__file__)) + cobol_script_path = os.path.join(script_dir, "payroll.cbl") + + if not os.path.exists(cobol_script_path): + raise FileNotFoundError(f"The COBOL script 'payroll.cbl' was not found in {script_dir}") # Always recompile to ensure we have the latest version - if os.path.exists("payroll"): - os.remove("payroll") + output_path = os.path.join(script_dir, "payroll") + if os.path.exists(output_path): + os.remove(output_path) print("Compiling payroll.cbl...") - compile_command = ["cobc", "-x", "-o", "payroll", "payroll.cbl"] + compile_command = ["cobc", "-x", "-o", output_path, cobol_script_path] try: subprocess.run(compile_command, check=True) print("Compilation successful.") @@ -222,36 +227,34 @@ def process_payroll_cobol(employee_records: List[EmployeeRecord]) -> List[Tuple[ return results -def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, float]]: # Python translation of cobol code +def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, float]]: # Python translation of COBOL code """ - Pure Python implementation of the COBOL payroll processing logic. - - This function performs the same calculations as the COBOL program but in Python. - It should perform the exact same result as process_payroll_cobol on all possible inputs, - and throw the same exceptions in the same scenarios. - - Args: - employee_records: List of EmployeeRecord objects containing payroll data - - Returns: - List of tuples containing (gross_pay, net_pay) for each employee - - TEST THIS PROPERTY: - Results should exactly match process_payroll_cobol() output, including thrown exceptions. - IE, for all ers: List[EmployeeRecord], process_payroll(er) == process_payroll_cobol(er), - unless either side throws an Exception, in which case the other side should throw an identical - exception. + Pure Python implementation of the COBOL payroll processing logic. + + This function performs the same calculations as the COBOL program but in Python. + It should perform the exact same result as process_payroll_cobol on all possible inputs, + and throw the same exceptions in the same scenarios. + + Args: + employee_records: List of EmployeeRecord objects containing payroll data + + Returns: + List of tuples containing (gross_pay, net_pay) for each employee + + TEST THIS PROPERTY: + Results should exactly match process_payroll_cobol() output, including thrown exceptions. + IE, for all ers: List[EmployeeRecord], process_payroll(er) == process_payroll_cobol(er), + unless either side throws an Exception, in which case the other side should throw an identical + exception. """ - results = [] - for record in employee_records: - # Calculate gross pay and net pay - gross_pay = record.hours_worked * record.hourly_rate - net_pay = gross_pay - record.tax_deduction - - # Display results - print(f"Employee ID: {record.emp_id}") - print(f"Gross Pay: ${gross_pay:.2f}") - print(f"Net Pay: ${net_pay:.2f}") - results.append((gross_pay, net_pay)) - - return results # this SHOULD return the same result as process_payroll_cobol(employee_records) + results = [] + for record in employee_records: + # Calculate gross pay and net pay + gross_pay = record.hours_worked * record.hourly_rate + net_pay = gross_pay - record.tax_deduction + # Display results + print(f"Employee ID: {record.emp_id}") + print(f"Gross Pay: ${gross_pay:.2f}") + print(f"Net Pay: ${net_pay:.2f}") + results.append((gross_pay, net_pay)) + return results # this should return the same result as process_payroll_cobol(employee_records) From 14e6982588d28a232eaaba3c2a5b90382940849d Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Fri, 10 Jan 2025 09:55:38 -0700 Subject: [PATCH 34/41] whitespace --- COBOL/script.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/COBOL/script.py b/COBOL/script.py index 413fbe5..a9c781c 100644 --- a/COBOL/script.py +++ b/COBOL/script.py @@ -227,7 +227,7 @@ def process_payroll_cobol(employee_records: List[EmployeeRecord]) -> List[Tuple[ return results -def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, float]]: # Python translation of COBOL code +def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, float]]: """ Pure Python implementation of the COBOL payroll processing logic. @@ -241,20 +241,20 @@ def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, Returns: List of tuples containing (gross_pay, net_pay) for each employee - TEST THIS PROPERTY: - Results should exactly match process_payroll_cobol() output, including thrown exceptions. - IE, for all ers: List[EmployeeRecord], process_payroll(er) == process_payroll_cobol(er), - unless either side throws an Exception, in which case the other side should throw an identical - exception. + ** TEST THIS PROPERTY **: + Results should exactly match process_payroll_cobol() output, including thrown exceptions. + IE, for all ers: List[EmployeeRecord], process_payroll(er) == process_payroll_cobol(er), + unless either side throws an Exception, in which case the other side should throw an identical + exception. """ - results = [] - for record in employee_records: - # Calculate gross pay and net pay - gross_pay = record.hours_worked * record.hourly_rate - net_pay = gross_pay - record.tax_deduction - # Display results - print(f"Employee ID: {record.emp_id}") - print(f"Gross Pay: ${gross_pay:.2f}") - print(f"Net Pay: ${net_pay:.2f}") - results.append((gross_pay, net_pay)) - return results # this should return the same result as process_payroll_cobol(employee_records) + results = [] + for record in employee_records: + # Calculate gross pay and net pay + gross_pay = record.hours_worked * record.hourly_rate + net_pay = gross_pay - record.tax_deduction + # Display results + print(f"Employee ID: {record.emp_id}") + print(f"Gross Pay: ${gross_pay:.2f}") + print(f"Net Pay: ${net_pay:.2f}") + results.append((gross_pay, net_pay)) + return results # this SHOULD return the same result as process_payroll_cobol(employee_records) From 14d854920b4539047dde47e9d980943945355131 Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Fri, 10 Jan 2025 10:13:04 -0700 Subject: [PATCH 35/41] Clarify WHAT to test --- COBOL/script.py | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/COBOL/script.py b/COBOL/script.py index a9c781c..a2db20c 100644 --- a/COBOL/script.py +++ b/COBOL/script.py @@ -227,7 +227,7 @@ def process_payroll_cobol(employee_records: List[EmployeeRecord]) -> List[Tuple[ return results -def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, float]]: +def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, float]]: """ Pure Python implementation of the COBOL payroll processing logic. @@ -241,20 +241,26 @@ def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, Returns: List of tuples containing (gross_pay, net_pay) for each employee - ** TEST THIS PROPERTY **: - Results should exactly match process_payroll_cobol() output, including thrown exceptions. - IE, for all ers: List[EmployeeRecord], process_payroll(er) == process_payroll_cobol(er), - unless either side throws an Exception, in which case the other side should throw an identical - exception. + ** TEST THIS PROPERTY ONLY **: + Results should exactly match process_payroll_cobol() output, including thrown exceptions. + IE, for all ers: List[EmployeeRecord], process_payroll(er) == process_payroll_cobol(er), + unless either side throws an Exception, in which case the other side should throw an identical + exception. + + Limit employee_records to 1-10 records for testing, as in the real world there will never be more than 10. + + Do NOT bother testing any other properties of this function. """ - results = [] - for record in employee_records: - # Calculate gross pay and net pay - gross_pay = record.hours_worked * record.hourly_rate - net_pay = gross_pay - record.tax_deduction + results = [] + for record in employee_records: + # Calculate gross pay and net pay + gross_pay = record.hours_worked * record.hourly_rate + net_pay = gross_pay - record.tax_deduction + # Display results - print(f"Employee ID: {record.emp_id}") - print(f"Gross Pay: ${gross_pay:.2f}") - print(f"Net Pay: ${net_pay:.2f}") - results.append((gross_pay, net_pay)) + print(f"Employee ID: {record.emp_id}") + print(f"Gross Pay: ${gross_pay:.2f}") + print(f"Net Pay: ${net_pay:.2f}") + results.append((gross_pay, net_pay)) + return results # this SHOULD return the same result as process_payroll_cobol(employee_records) From d06cec539b63edd061c52abec9e5fd3038451d30 Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Fri, 10 Jan 2025 10:39:59 -0700 Subject: [PATCH 36/41] fix cobol file path --- COBOL/script.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/COBOL/script.py b/COBOL/script.py index a2db20c..49d7789 100644 --- a/COBOL/script.py +++ b/COBOL/script.py @@ -174,10 +174,11 @@ def process_payroll_cobol(employee_records: List[EmployeeRecord]) -> List[Tuple[ # 4) Run the compiled COBOL program with the input file as an argument print(f"Running the COBOL payroll program with file: {temp_file}") + script_dir = os.path.dirname(os.path.abspath(__file__)) run_command = ["./payroll", temp_file] try: - result = subprocess.run(run_command, capture_output=True, text=True, check=True) + result = subprocess.run(run_command, capture_output=True, text=True, check=True, cwd=script_dir) except subprocess.CalledProcessError as e: print(f"Error running COBOL program. Exit code: {e.returncode}") print(f"Command that failed: {' '.join(e.cmd)}") From b8bdc68b03719ee930ae239c491e588658e375ee Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Fri, 10 Jan 2025 10:40:41 -0700 Subject: [PATCH 37/41] Indicate which function to test --- COBOL/script.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/COBOL/script.py b/COBOL/script.py index 49d7789..398ae66 100644 --- a/COBOL/script.py +++ b/COBOL/script.py @@ -228,7 +228,7 @@ def process_payroll_cobol(employee_records: List[EmployeeRecord]) -> List[Tuple[ return results -def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, float]]: +def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, float]]: """ Pure Python implementation of the COBOL payroll processing logic. @@ -242,15 +242,16 @@ def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, Returns: List of tuples containing (gross_pay, net_pay) for each employee - ** TEST THIS PROPERTY ONLY **: + ** PLEASE TEST THIS PROPERTY ONLY **: + Results should exactly match process_payroll_cobol() output, including thrown exceptions. - IE, for all ers: List[EmployeeRecord], process_payroll(er) == process_payroll_cobol(er), - unless either side throws an Exception, in which case the other side should throw an identical - exception. + IE, for all ers: List[EmployeeRecord], process_payroll(er) == process_payroll_cobol(er), + unless either side throws an Exception, in which case the other side should throw an identical + exception. - Limit employee_records to 1-10 records for testing, as in the real world there will never be more than 10. + Limit employee_records to 1-10 records for testing, as in the real world there will never be more than 10. - Do NOT bother testing any other properties of this function. + Please do NOT bother testing any other properties of this function. """ results = [] for record in employee_records: @@ -258,10 +259,10 @@ def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, gross_pay = record.hours_worked * record.hourly_rate net_pay = gross_pay - record.tax_deduction - # Display results - print(f"Employee ID: {record.emp_id}") - print(f"Gross Pay: ${gross_pay:.2f}") - print(f"Net Pay: ${net_pay:.2f}") - results.append((gross_pay, net_pay)) + # Display results + print(f"Employee ID: {record.emp_id}") + print(f"Gross Pay: ${gross_pay:.2f}") + print(f"Net Pay: ${net_pay:.2f}") + results.append((gross_pay, net_pay)) - return results # this SHOULD return the same result as process_payroll_cobol(employee_records) + return results # this should return the same result as process_payroll_cobol(employee_records) From 9b616e576ff7cf6328c7d6e2c4de6a317686b8a4 Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Fri, 10 Jan 2025 10:48:40 -0700 Subject: [PATCH 38/41] last ditch effort --- COBOL/script.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/COBOL/script.py b/COBOL/script.py index 398ae66..11a2594 100644 --- a/COBOL/script.py +++ b/COBOL/script.py @@ -153,7 +153,9 @@ def process_payroll_cobol(employee_records: List[EmployeeRecord]) -> List[Tuple[ # 3) Write data in the fixed-length format print("=== Debug: Writing the following lines to input file ===") - with open(temp_file, 'w', newline='') as f: + script_dir = os.path.dirname(os.path.abspath(__file__)) + temp_file_path = os.path.join(script_dir, temp_file) + with open(temp_file_path, 'w', newline='') as f: for record in employee_records: # EMP-ID: 5 chars emp_id_str = record.emp_id[:5].ljust(5) @@ -173,9 +175,8 @@ def process_payroll_cobol(employee_records: List[EmployeeRecord]) -> List[Tuple[ print("=======================================================") # 4) Run the compiled COBOL program with the input file as an argument - print(f"Running the COBOL payroll program with file: {temp_file}") - script_dir = os.path.dirname(os.path.abspath(__file__)) - run_command = ["./payroll", temp_file] + print(f"Running the COBOL payroll program with file: {temp_file_path}") + run_command = ["./payroll", temp_file_path] try: result = subprocess.run(run_command, capture_output=True, text=True, check=True, cwd=script_dir) From 1eeed48696c17886bbe97bca415bb8ac318e95ba Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Fri, 10 Jan 2025 10:49:23 -0700 Subject: [PATCH 39/41] Indicate which function to test --- COBOL/script.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/COBOL/script.py b/COBOL/script.py index 11a2594..b60847c 100644 --- a/COBOL/script.py +++ b/COBOL/script.py @@ -229,7 +229,7 @@ def process_payroll_cobol(employee_records: List[EmployeeRecord]) -> List[Tuple[ return results -def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, float]]: +def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, float]]: """ Pure Python implementation of the COBOL payroll processing logic. @@ -243,16 +243,16 @@ def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, Returns: List of tuples containing (gross_pay, net_pay) for each employee - ** PLEASE TEST THIS PROPERTY ONLY **: + PLEASE TEST THIS PROPERTY ONLY: - Results should exactly match process_payroll_cobol() output, including thrown exceptions. - IE, for all ers: List[EmployeeRecord], process_payroll(er) == process_payroll_cobol(er), - unless either side throws an Exception, in which case the other side should throw an identical - exception. + Results should exactly match process_payroll_cobol() output, including thrown exceptions. + IE, for all ers: List[EmployeeRecord], process_payroll(er) == process_payroll_cobol(er), + unless either side throws an Exception, in which case the other side should throw an identical + exception. - Limit employee_records to 1-10 records for testing, as in the real world there will never be more than 10. + --> Limit employee_records to 1-10 records for testing, as in the real world there will never be more than 10. - Please do NOT bother testing any other properties of this function. + --> Please do NOT bother testing any other properties of this function. """ results = [] for record in employee_records: @@ -261,9 +261,9 @@ def process_payroll(employee_records: List[EmployeeRecord]) -> List[Tuple[float, net_pay = gross_pay - record.tax_deduction # Display results - print(f"Employee ID: {record.emp_id}") - print(f"Gross Pay: ${gross_pay:.2f}") - print(f"Net Pay: ${net_pay:.2f}") - results.append((gross_pay, net_pay)) + print(f"Employee ID: {record.emp_id}") + print(f"Gross Pay: ${gross_pay:.2f}") + print(f"Net Pay: ${net_pay:.2f}") + results.append((gross_pay, net_pay)) - return results # this should return the same result as process_payroll_cobol(employee_records) + return results # this SHOULD return the same result as process_payroll_cobol(employee_records) From 12a89086acae1dc2b19658c57eccdd81b2551611 Mon Sep 17 00:00:00 2001 From: Max von Hippel Date: Fri, 10 Jan 2025 15:40:04 -0700 Subject: [PATCH 40/41] Improve README --- COBOL/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/COBOL/README.md b/COBOL/README.md index cef3b47..2d8ff8b 100644 --- a/COBOL/README.md +++ b/COBOL/README.md @@ -3,7 +3,9 @@ Astonishingly, 70% of all existing business logic is in COBOL, and 800 billion lines of COBOL are still in use in industry today [1]. Many (perhaps all) companies that still use COBOL wish they could move off it, since it is massively antiquated and the only living engineers who still know it are in retirement homes. Obviously, LLMs present a compelling solution to this problem via automated translation. But how can you be sure the translation is correct? This demo is meant to illustrate how Benchify can fit into the analysis of a translation from COBOL to Python. -Example usage: +You can see the complete report [here](https://github.com/Benchify/benchify-examples/pull/134). + +Example usage of the COBOL wrapper: ``` ipython3 Python 3.9.6 (default, Nov 11 2024, 03:15:38) From cdb91d4a1d4afd8ae1f7d2e0ab0361ca81bc6cb7 Mon Sep 17 00:00:00 2001 From: juancastano Date: Wed, 5 Feb 2025 16:49:16 -0800 Subject: [PATCH 41/41] creating test file --- Typescript/myFile.ts | 43 ++++ Typescript/node_modules/.bin/tsc | 1 + Typescript/node_modules/.bin/tsserver | 1 + Typescript/node_modules/.package-lock.json | 20 ++ .../node_modules/typescript/LICENSE.txt | 55 +++++ Typescript/node_modules/typescript/README.md | 50 +++++ .../node_modules/typescript/SECURITY.md | 41 ++++ .../typescript/ThirdPartyNoticeText.txt | 193 ++++++++++++++++++ Typescript/node_modules/typescript/bin/tsc | 2 + .../node_modules/typescript/bin/tsserver | 2 + .../node_modules/typescript/package.json | 120 +++++++++++ Typescript/package-lock.json | 25 +++ Typescript/package.json | 8 + Typescript/tsconfig.json | 111 ++++++++++ 14 files changed, 672 insertions(+) create mode 100644 Typescript/myFile.ts create mode 120000 Typescript/node_modules/.bin/tsc create mode 120000 Typescript/node_modules/.bin/tsserver create mode 100644 Typescript/node_modules/.package-lock.json create mode 100644 Typescript/node_modules/typescript/LICENSE.txt create mode 100644 Typescript/node_modules/typescript/README.md create mode 100644 Typescript/node_modules/typescript/SECURITY.md create mode 100644 Typescript/node_modules/typescript/ThirdPartyNoticeText.txt create mode 100755 Typescript/node_modules/typescript/bin/tsc create mode 100755 Typescript/node_modules/typescript/bin/tsserver create mode 100644 Typescript/node_modules/typescript/package.json create mode 100644 Typescript/package-lock.json create mode 100644 Typescript/package.json create mode 100644 Typescript/tsconfig.json diff --git a/Typescript/myFile.ts b/Typescript/myFile.ts new file mode 100644 index 0000000..caaf007 --- /dev/null +++ b/Typescript/myFile.ts @@ -0,0 +1,43 @@ +/** + * Calculates the Levenshtein distance between two strings using dynamic programming. + * The Levenshtein distance is the minimum number of single-character edits + * (insertions, deletions, or substitutions) required to change one string into another. + * + * @param str1 The first string + * @param str2 The second string + * @returns The Levenshtein distance between the two strings + */ +function getStringDistance(str1: string, str2: string): number { + const m = str1.length; + const n = str2.length; + + // Create a matrix of size (m+1) x (n+1) + const dp: number[][] = Array(m + 1).fill(null) + .map(() => Array(n + 1).fill(0)); + + // Initialize first row and column + for (let i = 0; i <= m; i++) { + dp[i][0] = i; + } + for (let j = 0; j <= n; j++) { + dp[0][j] = j; + } + + // Fill the matrix + for (let i = 1; i <= m; i++) { + for (let j = 1; j <= n; j++) { + if (str1[i - 1] === str2[j - 1]) { + dp[i][j] = dp[i - 1][j - 1]; + } else { + dp[i][j] = Math.min( + dp[i - 1][j] + 1, // deletion + dp[i][j - 1] + 1, // insertion + dp[i - 1][j - 1] + 1 // substitution + ); + } + } + } + + // Return the bottom-right cell of the matrix + return dp[m][n]; +} diff --git a/Typescript/node_modules/.bin/tsc b/Typescript/node_modules/.bin/tsc new file mode 120000 index 0000000..0863208 --- /dev/null +++ b/Typescript/node_modules/.bin/tsc @@ -0,0 +1 @@ +../typescript/bin/tsc \ No newline at end of file diff --git a/Typescript/node_modules/.bin/tsserver b/Typescript/node_modules/.bin/tsserver new file mode 120000 index 0000000..f8f8f1a --- /dev/null +++ b/Typescript/node_modules/.bin/tsserver @@ -0,0 +1 @@ +../typescript/bin/tsserver \ No newline at end of file diff --git a/Typescript/node_modules/.package-lock.json b/Typescript/node_modules/.package-lock.json new file mode 100644 index 0000000..2d40d36 --- /dev/null +++ b/Typescript/node_modules/.package-lock.json @@ -0,0 +1,20 @@ +{ + "name": "Typescript", + "lockfileVersion": 3, + "requires": true, + "packages": { + "node_modules/typescript": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", + "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + } + } +} diff --git a/Typescript/node_modules/typescript/LICENSE.txt b/Typescript/node_modules/typescript/LICENSE.txt new file mode 100644 index 0000000..8746124 --- /dev/null +++ b/Typescript/node_modules/typescript/LICENSE.txt @@ -0,0 +1,55 @@ +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of this License; and + +You must cause any modified files to carry prominent notices stating that You changed the files; and + +You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + +If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff --git a/Typescript/node_modules/typescript/README.md b/Typescript/node_modules/typescript/README.md new file mode 100644 index 0000000..3314c58 --- /dev/null +++ b/Typescript/node_modules/typescript/README.md @@ -0,0 +1,50 @@ + +# TypeScript + +[![GitHub Actions CI](https://github.com/microsoft/TypeScript/workflows/CI/badge.svg)](https://github.com/microsoft/TypeScript/actions?query=workflow%3ACI) +[![npm version](https://badge.fury.io/js/typescript.svg)](https://www.npmjs.com/package/typescript) +[![Downloads](https://img.shields.io/npm/dm/typescript.svg)](https://www.npmjs.com/package/typescript) +[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/microsoft/TypeScript/badge)](https://securityscorecards.dev/viewer/?uri=github.com/microsoft/TypeScript) + + +[TypeScript](https://www.typescriptlang.org/) is a language for application-scale JavaScript. TypeScript adds optional types to JavaScript that support tools for large-scale JavaScript applications for any browser, for any host, on any OS. TypeScript compiles to readable, standards-based JavaScript. Try it out at the [playground](https://www.typescriptlang.org/play/), and stay up to date via [our blog](https://blogs.msdn.microsoft.com/typescript) and [Twitter account](https://twitter.com/typescript). + +Find others who are using TypeScript at [our community page](https://www.typescriptlang.org/community/). + +## Installing + +For the latest stable version: + +```bash +npm install -D typescript +``` + +For our nightly builds: + +```bash +npm install -D typescript@next +``` + +## Contribute + +There are many ways to [contribute](https://github.com/microsoft/TypeScript/blob/main/CONTRIBUTING.md) to TypeScript. +* [Submit bugs](https://github.com/microsoft/TypeScript/issues) and help us verify fixes as they are checked in. +* Review the [source code changes](https://github.com/microsoft/TypeScript/pulls). +* Engage with other TypeScript users and developers on [StackOverflow](https://stackoverflow.com/questions/tagged/typescript). +* Help each other in the [TypeScript Community Discord](https://discord.gg/typescript). +* Join the [#typescript](https://twitter.com/search?q=%23TypeScript) discussion on Twitter. +* [Contribute bug fixes](https://github.com/microsoft/TypeScript/blob/main/CONTRIBUTING.md). + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see +the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) +with any additional questions or comments. + +## Documentation + +* [TypeScript in 5 minutes](https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html) +* [Programming handbook](https://www.typescriptlang.org/docs/handbook/intro.html) +* [Homepage](https://www.typescriptlang.org/) + +## Roadmap + +For details on our planned features and future direction, please refer to our [roadmap](https://github.com/microsoft/TypeScript/wiki/Roadmap). diff --git a/Typescript/node_modules/typescript/SECURITY.md b/Typescript/node_modules/typescript/SECURITY.md new file mode 100644 index 0000000..b3c89ef --- /dev/null +++ b/Typescript/node_modules/typescript/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet) and [Xamarin](https://github.com/xamarin). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/security.md/definition), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/security.md/msrc/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/security.md/msrc/pgp). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + + * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) + * Full paths of source file(s) related to the manifestation of the issue + * The location of the affected source code (tag/branch/commit or direct URL) + * Any special configuration required to reproduce the issue + * Step-by-step instructions to reproduce the issue + * Proof-of-concept or exploit code (if possible) + * Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/security.md/msrc/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/security.md/cvd). + + diff --git a/Typescript/node_modules/typescript/ThirdPartyNoticeText.txt b/Typescript/node_modules/typescript/ThirdPartyNoticeText.txt new file mode 100644 index 0000000..a857fb3 --- /dev/null +++ b/Typescript/node_modules/typescript/ThirdPartyNoticeText.txt @@ -0,0 +1,193 @@ +/*!----------------- TypeScript ThirdPartyNotices ------------------------------------------------------- + +The TypeScript software incorporates third party material from the projects listed below. The original copyright notice and the license under which Microsoft received such third party material are set forth below. Microsoft reserves all other rights not expressly granted, whether by implication, estoppel or otherwise. + +--------------------------------------------- +Third Party Code Components +-------------------------------------------- + +------------------- DefinitelyTyped -------------------- +This file is based on or incorporates material from the projects listed below (collectively "Third Party Code"). Microsoft is not the original author of the Third Party Code. The original copyright notice and the license, under which Microsoft received such Third Party Code, are set forth below. Such licenses and notices are provided for informational purposes only. Microsoft, not the third party, licenses the Third Party Code to you under the terms set forth in the EULA for the Microsoft Product. Microsoft reserves all other rights not expressly granted under this agreement, whether by implication, estoppel or otherwise. +DefinitelyTyped +This project is licensed under the MIT license. Copyrights are respective of each contributor listed at the beginning of each definition file. Provided for Informational Purposes Only + +MIT License +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-------------------------------------------------------------------------------------- + +------------------- Unicode -------------------- +UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE + +Unicode Data Files include all data files under the directories +http://www.unicode.org/Public/, http://www.unicode.org/reports/, +http://www.unicode.org/cldr/data/, http://source.icu-project.org/repos/icu/, and +http://www.unicode.org/utility/trac/browser/. + +Unicode Data Files do not include PDF online code charts under the +directory http://www.unicode.org/Public/. + +Software includes any source code published in the Unicode Standard +or under the directories +http://www.unicode.org/Public/, http://www.unicode.org/reports/, +http://www.unicode.org/cldr/data/, http://source.icu-project.org/repos/icu/, and +http://www.unicode.org/utility/trac/browser/. + +NOTICE TO USER: Carefully read the following legal agreement. +BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S +DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), +YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE +TERMS AND CONDITIONS OF THIS AGREEMENT. +IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE +THE DATA FILES OR SOFTWARE. + +COPYRIGHT AND PERMISSION NOTICE + +Copyright (c) 1991-2017 Unicode, Inc. All rights reserved. +Distributed under the Terms of Use in http://www.unicode.org/copyright.html. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Unicode data files and any associated documentation +(the "Data Files") or Unicode software and any associated documentation +(the "Software") to deal in the Data Files or Software +without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, and/or sell copies of +the Data Files or Software, and to permit persons to whom the Data Files +or Software are furnished to do so, provided that either +(a) this copyright and permission notice appear with all copies +of the Data Files or Software, or +(b) this copyright and permission notice appear in associated +Documentation. + +THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT OF THIRD PARTY RIGHTS. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS +NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL +DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THE DATA FILES OR SOFTWARE. + +Except as contained in this notice, the name of a copyright holder +shall not be used in advertising or otherwise to promote the sale, +use or other dealings in these Data Files or Software without prior +written authorization of the copyright holder. +------------------------------------------------------------------------------------- + +-------------------Document Object Model----------------------------- +DOM + +W3C License +This work is being provided by the copyright holders under the following license. +By obtaining and/or copying this work, you (the licensee) agree that you have read, understood, and will comply with the following terms and conditions. +Permission to copy, modify, and distribute this work, with or without modification, for any purpose and without fee or royalty is hereby granted, provided that you include the following +on ALL copies of the work or portions thereof, including modifications: +* The full text of this NOTICE in a location viewable to users of the redistributed or derivative work. +* Any pre-existing intellectual property disclaimers, notices, or terms and conditions. If none exist, the W3C Software and Document Short Notice should be included. +* Notice of any changes or modifications, through a copyright statement on the new code or document such as "This software or document includes material copied from or derived +from [title and URI of the W3C document]. Copyright © [YEAR] W3C® (MIT, ERCIM, Keio, Beihang)." +Disclaimers +THIS WORK IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR +FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENT WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. +COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENT. +The name and trademarks of copyright holders may NOT be used in advertising or publicity pertaining to the work without specific, written prior permission. +Title to copyright in this work will at all times remain with copyright holders. + +--------- + +DOM +Copyright © 2018 WHATWG (Apple, Google, Mozilla, Microsoft). This work is licensed under a Creative Commons Attribution 4.0 International License: Attribution 4.0 International +======================================================================= +Creative Commons Corporation ("Creative Commons") is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an "as-is" basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible. Using Creative Commons Public Licenses Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses. Considerations for licensors: Our public licenses are intended for use by those authorized to give the public permission to use material in ways otherwise restricted by copyright and certain other rights. Our licenses are irrevocable. Licensors should read and understand the terms and conditions of the license they choose before applying it. Licensors should also secure all rights necessary before applying our licenses so that the public can reuse the material as expected. Licensors should clearly mark any material not subject to the license. This includes other CC- licensed material, or material used under an exception or limitation to copyright. More considerations for licensors: + +wiki.creativecommons.org/Considerations_for_licensors Considerations for the public: By using one of our public licenses, a licensor grants the public permission to use the licensed material under specified terms and conditions. If the licensor's permission is not necessary for any reason--for example, because of any applicable exception or limitation to copyright--then that use is not regulated by the license. Our licenses grant only permissions under copyright and certain other rights that a licensor has authority to grant. Use of the licensed material may still be restricted for other reasons, including because others have copyright or other rights in the material. A licensor may make special requests, such as asking that all changes be marked or described. Although not required by our licenses, you are encouraged to respect those requests where reasonable. More_considerations for the public: wiki.creativecommons.org/Considerations_for_licensees ======================================================================= +Creative Commons Attribution 4.0 International Public License By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions. Section 1 -- Definitions. a. Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image. b. Adapter's License means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License. c. Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. d. Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements. e. Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material. f. Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License. g. Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license. h. Licensor means the individual(s) or entity(ies) granting rights under this Public License. i. Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them. j. Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world. k. You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning. Section 2 -- Scope. a. License grant. 1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: a. reproduce and Share the Licensed Material, in whole or in part; and b. produce, reproduce, and Share Adapted Material. 2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. 3. Term. The term of this Public License is specified in Section 6(a). 4. Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a) (4) never produces Adapted Material. 5. Downstream recipients. a. Offer from the Licensor -- Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. b. No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. 6. No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). b. Other rights. 1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. 2. Patent and trademark rights are not licensed under this Public License. 3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties. Section 3 -- License Conditions. Your exercise of the Licensed Rights is expressly made subject to the following conditions. a. Attribution. 1. If You Share the Licensed Material (including in modified form), You must: a. retain the following if it is supplied by the Licensor with the Licensed Material: i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); ii. a copyright notice; iii. a notice that refers to this Public License; iv. a notice that refers to the disclaimer of warranties; v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; b. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and c. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. 2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. 3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. 4. If You Share Adapted Material You produce, the Adapter's License You apply must not prevent recipients of the Adapted Material from complying with this Public License. Section 4 -- Sui Generis Database Rights. Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database; b. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and c. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database. For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. Section 5 -- Disclaimer of Warranties and Limitation of Liability. a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. Section 6 -- Term and Termination. a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: 1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or 2. upon express reinstatement by the Licensor. For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License. c. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License. d. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. Section 7 -- Other Terms and Conditions. a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. Section 8 -- Interpretation. a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. b. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions. c. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor. d. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority. ======================================================================= Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the "Licensor." Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at creativecommons.org/policies, Creative Commons does not authorize the use of the trademark "Creative Commons" or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses. Creative Commons may be contacted at creativecommons.org. + +-------------------------------------------------------------------------------- + +----------------------Web Background Synchronization------------------------------ + +Web Background Synchronization Specification +Portions of spec © by W3C + +W3C Community Final Specification Agreement +To secure commitments from participants for the full text of a Community or Business Group Report, the group may call for voluntary commitments to the following terms; a "summary" is +available. See also the related "W3C Community Contributor License Agreement". +1. The Purpose of this Agreement. +This Agreement sets forth the terms under which I make certain copyright and patent rights available to you for your implementation of the Specification. +Any other capitalized terms not specifically defined herein have the same meaning as those terms have in the "W3C Patent Policy", and if not defined there, in the "W3C Process Document". +2. Copyrights. +2.1. Copyright Grant. I grant to you a perpetual (for the duration of the applicable copyright), worldwide, non-exclusive, no-charge, royalty-free, copyright license, without any obligation for accounting to me, to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, distribute, and implement the Specification to the full extent of my copyright interest in the Specification. +2.2. Attribution. As a condition of the copyright grant, you must include an attribution to the Specification in any derivative work you make based on the Specification. That attribution must include, at minimum, the Specification name and version number. +3. Patents. +3.1. Patent Licensing Commitment. I agree to license my Essential Claims under the W3C Community RF Licensing Requirements. This requirement includes Essential Claims that I own and any that I have the right to license without obligation of payment or other consideration to an unrelated third party. W3C Community RF Licensing Requirements obligations made concerning the Specification and described in this policy are binding on me for the life of the patents in question and encumber the patents containing Essential Claims, regardless of changes in participation status or W3C Membership. I also agree to license my Essential Claims under the W3C Community RF Licensing Requirements in derivative works of the Specification so long as all normative portions of the Specification are maintained and that this licensing commitment does not extend to any portion of the derivative work that was not included in the Specification. +3.2. Optional, Additional Patent Grant. In addition to the provisions of Section 3.1, I may also, at my option, make certain intellectual property rights infringed by implementations of the Specification, including Essential Claims, available by providing those terms via the W3C Web site. +4. No Other Rights. Except as specifically set forth in this Agreement, no other express or implied patent, trademark, copyright, or other property rights are granted under this Agreement, including by implication, waiver, or estoppel. +5. Antitrust Compliance. I acknowledge that I may compete with other participants, that I am under no obligation to implement the Specification, that each participant is free to develop competing technologies and standards, and that each party is free to license its patent rights to third parties, including for the purpose of enabling competing technologies and standards. +6. Non-Circumvention. I agree that I will not intentionally take or willfully assist any third party to take any action for the purpose of circumventing my obligations under this Agreement. +7. Transition to W3C Recommendation Track. The Specification developed by the Project may transition to the W3C Recommendation Track. The W3C Team is responsible for notifying me that a Corresponding Working Group has been chartered. I have no obligation to join the Corresponding Working Group. If the Specification developed by the Project transitions to the W3C Recommendation Track, the following terms apply: +7.1. If I join the Corresponding Working Group. If I join the Corresponding Working Group, I will be subject to all W3C rules, obligations, licensing commitments, and policies that govern that Corresponding Working Group. +7.2. If I Do Not Join the Corresponding Working Group. +7.2.1. Licensing Obligations to Resulting Specification. If I do not join the Corresponding Working Group, I agree to offer patent licenses according to the W3C Royalty-Free licensing requirements described in Section 5 of the W3C Patent Policy for the portions of the Specification included in the resulting Recommendation. This licensing commitment does not extend to any portion of an implementation of the Recommendation that was not included in the Specification. This licensing commitment may not be revoked but may be modified through the exclusion process defined in Section 4 of the W3C Patent Policy. I am not required to join the Corresponding Working Group to exclude patents from the W3C Royalty-Free licensing commitment, but must otherwise follow the normal exclusion procedures defined by the W3C Patent Policy. The W3C Team will notify me of any Call for Exclusion in the Corresponding Working Group as set forth in Section 4.5 of the W3C Patent Policy. +7.2.2. No Disclosure Obligation. If I do not join the Corresponding Working Group, I have no patent disclosure obligations outside of those set forth in Section 6 of the W3C Patent Policy. +8. Conflict of Interest. I will disclose significant relationships when those relationships might reasonably be perceived as creating a conflict of interest with my role. I will notify W3C of any change in my affiliation using W3C-provided mechanisms. +9. Representations, Warranties and Disclaimers. I represent and warrant that I am legally entitled to grant the rights and promises set forth in this Agreement. IN ALL OTHER RESPECTS THE SPECIFICATION IS PROVIDED “AS IS.” The entire risk as to implementing or otherwise using the Specification is assumed by the implementer and user. Except as stated herein, I expressly disclaim any warranties (express, implied, or otherwise), including implied warranties of merchantability, non-infringement, fitness for a particular purpose, or title, related to the Specification. IN NO EVENT WILL ANY PARTY BE LIABLE TO ANY OTHER PARTY FOR LOST PROFITS OR ANY FORM OF INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER FROM ANY CAUSES OF ACTION OF ANY KIND WITH RESPECT TO THIS AGREEMENT, WHETHER BASED ON BREACH OF CONTRACT, TORT (INCLUDING NEGLIGENCE), OR OTHERWISE, AND WHETHER OR NOT THE OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. All of my obligations under Section 3 regarding the transfer, successors in interest, or assignment of Granted Claims will be satisfied if I notify the transferee or assignee of any patent that I know contains Granted Claims of the obligations under Section 3. Nothing in this Agreement requires me to undertake a patent search. +10. Definitions. +10.1. Agreement. “Agreement” means this W3C Community Final Specification Agreement. +10.2. Corresponding Working Group. “Corresponding Working Group” is a W3C Working Group that is chartered to develop a Recommendation, as defined in the W3C Process Document, that takes the Specification as an input. +10.3. Essential Claims. “Essential Claims” shall mean all claims in any patent or patent application in any jurisdiction in the world that would necessarily be infringed by implementation of the Specification. A claim is necessarily infringed hereunder only when it is not possible to avoid infringing it because there is no non-infringing alternative for implementing the normative portions of the Specification. Existence of a non-infringing alternative shall be judged based on the state of the art at the time of the publication of the Specification. The following are expressly excluded from and shall not be deemed to constitute Essential Claims: +10.3.1. any claims other than as set forth above even if contained in the same patent as Essential Claims; and +10.3.2. claims which would be infringed only by: +portions of an implementation that are not specified in the normative portions of the Specification, or +enabling technologies that may be necessary to make or use any product or portion thereof that complies with the Specification and are not themselves expressly set forth in the Specification (e.g., semiconductor manufacturing technology, compiler technology, object-oriented technology, basic operating system technology, and the like); or +the implementation of technology developed elsewhere and merely incorporated by reference in the body of the Specification. +10.3.3. design patents and design registrations. +For purposes of this definition, the normative portions of the Specification shall be deemed to include only architectural and interoperability requirements. Optional features in the RFC 2119 sense are considered normative unless they are specifically identified as informative. Implementation examples or any other material that merely illustrate the requirements of the Specification are informative, rather than normative. +10.4. I, Me, or My. “I,” “me,” or “my” refers to the signatory. +10.5 Project. “Project” means the W3C Community Group or Business Group for which I executed this Agreement. +10.6. Specification. “Specification” means the Specification identified by the Project as the target of this agreement in a call for Final Specification Commitments. W3C shall provide the authoritative mechanisms for the identification of this Specification. +10.7. W3C Community RF Licensing Requirements. “W3C Community RF Licensing Requirements” license shall mean a non-assignable, non-sublicensable license to make, have made, use, sell, have sold, offer to sell, import, and distribute and dispose of implementations of the Specification that: +10.7.1. shall be available to all, worldwide, whether or not they are W3C Members; +10.7.2. shall extend to all Essential Claims owned or controlled by me; +10.7.3. may be limited to implementations of the Specification, and to what is required by the Specification; +10.7.4. may be conditioned on a grant of a reciprocal RF license (as defined in this policy) to all Essential Claims owned or controlled by the licensee. A reciprocal license may be required to be available to all, and a reciprocal license may itself be conditioned on a further reciprocal license from all. +10.7.5. may not be conditioned on payment of royalties, fees or other consideration; +10.7.6. may be suspended with respect to any licensee when licensor issued by licensee for infringement of claims essential to implement the Specification or any W3C Recommendation; +10.7.7. may not impose any further conditions or restrictions on the use of any technology, intellectual property rights, or other restrictions on behavior of the licensee, but may include reasonable, customary terms relating to operation or maintenance of the license relationship such as the following: choice of law and dispute resolution; +10.7.8. shall not be considered accepted by an implementer who manifests an intent not to accept the terms of the W3C Community RF Licensing Requirements license as offered by the licensor. +10.7.9. The RF license conforming to the requirements in this policy shall be made available by the licensor as long as the Specification is in effect. The term of such license shall be for the life of the patents in question. +I am encouraged to provide a contact from which licensing information can be obtained and other relevant licensing information. Any such information will be made publicly available. +10.8. You or Your. “You,” “you,” or “your” means any person or entity who exercises copyright or patent rights granted under this Agreement, and any person that person or entity controls. + +------------------------------------------------------------------------------------- + +------------------- WebGL ----------------------------- +Copyright (c) 2018 The Khronos Group Inc. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and/or associated documentation files (the +"Materials"), to deal in the Materials without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Materials, and to +permit persons to whom the Materials are furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Materials. + +THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +------------------------------------------------------ + +------------- End of ThirdPartyNotices ------------------------------------------- */ + diff --git a/Typescript/node_modules/typescript/bin/tsc b/Typescript/node_modules/typescript/bin/tsc new file mode 100755 index 0000000..19c62bf --- /dev/null +++ b/Typescript/node_modules/typescript/bin/tsc @@ -0,0 +1,2 @@ +#!/usr/bin/env node +require('../lib/tsc.js') diff --git a/Typescript/node_modules/typescript/bin/tsserver b/Typescript/node_modules/typescript/bin/tsserver new file mode 100755 index 0000000..7143b6a --- /dev/null +++ b/Typescript/node_modules/typescript/bin/tsserver @@ -0,0 +1,2 @@ +#!/usr/bin/env node +require('../lib/tsserver.js') diff --git a/Typescript/node_modules/typescript/package.json b/Typescript/node_modules/typescript/package.json new file mode 100644 index 0000000..7b3d160 --- /dev/null +++ b/Typescript/node_modules/typescript/package.json @@ -0,0 +1,120 @@ +{ + "name": "typescript", + "author": "Microsoft Corp.", + "homepage": "https://www.typescriptlang.org/", + "version": "5.7.3", + "license": "Apache-2.0", + "description": "TypeScript is a language for application scale JavaScript development", + "keywords": [ + "TypeScript", + "Microsoft", + "compiler", + "language", + "javascript" + ], + "bugs": { + "url": "https://github.com/microsoft/TypeScript/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/microsoft/TypeScript.git" + }, + "main": "./lib/typescript.js", + "typings": "./lib/typescript.d.ts", + "bin": { + "tsc": "./bin/tsc", + "tsserver": "./bin/tsserver" + }, + "engines": { + "node": ">=14.17" + }, + "files": [ + "bin", + "lib", + "!lib/enu", + "LICENSE.txt", + "README.md", + "SECURITY.md", + "ThirdPartyNoticeText.txt", + "!**/.gitattributes" + ], + "devDependencies": { + "@dprint/formatter": "^0.4.1", + "@dprint/typescript": "0.93.0", + "@esfx/canceltoken": "^1.0.0", + "@eslint/js": "^9.11.1", + "@octokit/rest": "^21.0.2", + "@types/chai": "^4.3.20", + "@types/diff": "^5.2.2", + "@types/minimist": "^1.2.5", + "@types/mocha": "^10.0.8", + "@types/ms": "^0.7.34", + "@types/node": "latest", + "@types/source-map-support": "^0.5.10", + "@types/which": "^3.0.4", + "@typescript-eslint/rule-tester": "^8.8.0", + "@typescript-eslint/type-utils": "^8.8.0", + "@typescript-eslint/utils": "^8.8.0", + "azure-devops-node-api": "^14.1.0", + "c8": "^10.1.2", + "chai": "^4.5.0", + "chalk": "^4.1.2", + "chokidar": "^3.6.0", + "diff": "^5.2.0", + "dprint": "^0.47.2", + "esbuild": "^0.24.0", + "eslint": "^9.11.1", + "eslint-formatter-autolinkable-stylish": "^1.4.0", + "eslint-plugin-regexp": "^2.6.0", + "fast-xml-parser": "^4.5.0", + "glob": "^10.4.5", + "globals": "^15.9.0", + "hereby": "^1.10.0", + "jsonc-parser": "^3.3.1", + "knip": "^5.30.6", + "minimist": "^1.2.8", + "mocha": "^10.7.3", + "mocha-fivemat-progress-reporter": "^0.1.0", + "monocart-coverage-reports": "^2.11.0", + "ms": "^2.1.3", + "playwright": "^1.47.2", + "source-map-support": "^0.5.21", + "tslib": "^2.7.0", + "typescript": "^5.6.2", + "typescript-eslint": "^8.8.0", + "which": "^3.0.1" + }, + "overrides": { + "typescript@*": "$typescript" + }, + "scripts": { + "test": "hereby runtests-parallel --light=false", + "test:eslint-rules": "hereby run-eslint-rules-tests", + "build": "npm run build:compiler && npm run build:tests", + "build:compiler": "hereby local", + "build:tests": "hereby tests", + "build:tests:notypecheck": "hereby tests --no-typecheck", + "clean": "hereby clean", + "gulp": "hereby", + "lint": "hereby lint", + "knip": "hereby knip", + "format": "dprint fmt", + "setup-hooks": "node scripts/link-hooks.mjs" + }, + "browser": { + "fs": false, + "os": false, + "path": false, + "crypto": false, + "buffer": false, + "source-map-support": false, + "inspector": false, + "perf_hooks": false + }, + "packageManager": "npm@8.19.4", + "volta": { + "node": "20.1.0", + "npm": "8.19.4" + }, + "gitHead": "a5e123d9e0690fcea92878ea8a0a382922009fc9" +} diff --git a/Typescript/package-lock.json b/Typescript/package-lock.json new file mode 100644 index 0000000..36a5d33 --- /dev/null +++ b/Typescript/package-lock.json @@ -0,0 +1,25 @@ +{ + "name": "Typescript", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "typescript": "^5.7.3" + } + }, + "node_modules/typescript": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", + "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + } + } +} diff --git a/Typescript/package.json b/Typescript/package.json new file mode 100644 index 0000000..85f90db --- /dev/null +++ b/Typescript/package.json @@ -0,0 +1,8 @@ +{ + "scripts": { + "build": "tsc" + }, + "dependencies": { + "typescript": "^5.7.3" + } +} \ No newline at end of file diff --git a/Typescript/tsconfig.json b/Typescript/tsconfig.json new file mode 100644 index 0000000..c9c555d --- /dev/null +++ b/Typescript/tsconfig.json @@ -0,0 +1,111 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ + // "rewriteRelativeImportExtensions": true, /* Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files. */ + // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ + // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ + // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "noUncheckedSideEffectImports": true, /* Check side effect imports. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ + // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "strictBuiltinIteratorReturn": true, /* Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +}