diff --git a/.coverage b/.coverage new file mode 100644 index 0000000..948f233 Binary files /dev/null and b/.coverage differ diff --git a/.github/workflows/python-tests.yml b/.github/workflows/python-tests.yml new file mode 100644 index 0000000..d48a044 --- /dev/null +++ b/.github/workflows/python-tests.yml @@ -0,0 +1,26 @@ +name: Python package + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.10", "3.13"] + + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + # This case we are only updating pip, but you could add other dependencies if needed. + run: | + python -m pip install --upgrade pip + python -m pip install pytest + - name: Test with pytest + run: | + pytest diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..2c07333 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.11 diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..3e99ede --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "python.testing.pytestArgs": [ + "." + ], + "python.testing.unittestEnabled": false, + "python.testing.pytestEnabled": true +} \ No newline at end of file diff --git a/__pycache__/test_times.cpython-311-pytest-8.4.1.pyc b/__pycache__/test_times.cpython-311-pytest-8.4.1.pyc new file mode 100644 index 0000000..ce04afd Binary files /dev/null and b/__pycache__/test_times.cpython-311-pytest-8.4.1.pyc differ diff --git a/__pycache__/times.cpython-311.pyc b/__pycache__/times.cpython-311.pyc new file mode 100644 index 0000000..079cd98 Binary files /dev/null and b/__pycache__/times.cpython-311.pyc differ diff --git a/main.py b/main.py new file mode 100644 index 0000000..cbc4f86 --- /dev/null +++ b/main.py @@ -0,0 +1,6 @@ +def main(): + print("Hello from time-tests!") + + +if __name__ == "__main__": + main() diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..2ae6215 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,12 @@ +[project] +name = "time-tests" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.11" +dependencies = [] + +[dependency-groups] +dev = [ + "pytest>=8.4.1", +] diff --git a/test_times.py b/test_times.py new file mode 100644 index 0000000..8ba4240 --- /dev/null +++ b/test_times.py @@ -0,0 +1,82 @@ +from times import time_range, compute_overlap_time, iss_passes +from pytest import raises +from unittest.mock import patch +import requests +import mock +import responses + +def test_short_large(): + large = time_range("2010-01-12 10:00:00", "2010-01-12 12:00:00") + short = time_range("2010-01-12 10:30:00", "2010-01-12 10:45:00", 2, 60) + expected = [('2010-01-12 10:30:00', '2010-01-12 10:37:00'), ('2010-01-12 10:38:00', '2010-01-12 10:45:00')] + result = compute_overlap_time(short, large) + assert result == expected + +def test_large_short(): + large = time_range("2010-01-12 10:00:00", "2010-01-12 12:00:00") + short = time_range("2010-01-12 10:30:00", "2010-01-12 10:45:00", 2, 60) + expected = [('2010-01-12 10:30:00', '2010-01-12 10:37:00'), ('2010-01-12 10:38:00', '2010-01-12 10:45:00')] + result = compute_overlap_time(large, short) + assert result == expected + +def test_no_overlap(): + time_1 = time_range("2010-01-12 10:00:00", "2010-01-12 12:00:00") + time_2 = time_range("2010-01-12 13:00:00", "2010-01-12 14:00:00", 2, 60) + expected = [] + result = compute_overlap_time(time_1, time_2) + assert result == expected + +def text_overlap(): + time_1 = time_range("2010-01-12 10:00:00", "2010-01-12 14:35:00") + time_2 = time_range("2010-01-12 13:00:00", "2010-01-12 15:00:00") + expected = [] + result = compute_overlap_time(time_1, time_2) + assert result == expected + +def test_gaps(): + time_1 = time_range("2010-01-12 10:00:00", "2010-01-12 16:00:00", 2, 120*60) + time_2 = time_range("2010-01-12 10:00:00", "2010-01-12 16:00:00", 2, 60*60) + expected = [('2010-01-12 10:00:00', '2010-01-12 12:00:00'), ('2010-01-12 14:00:00', '2010-01-12 16:00:00')] + result = compute_overlap_time(time_1, time_2) + assert result == expected + +def test_startend(): + time_1 = time_range("2010-01-12 10:00:00", "2010-01-12 12:00:00") + time_2 = time_range("2010-01-12 12:00:00", "2010-01-12 16:00:00", 2, 60) + expected = [] + result = compute_overlap_time(time_1, time_2) + assert result == expected + +def test_endstart_error(): + with raises(ValueError, match=r"Start time is after the end time."): + time_range("2010-01-12 13:00:00", "2010-01-12 12:00:00") + +def test_interval_error(): + with raises(ValueError, match=r".* number of intervals is not a positive integer.*"): + time_range("2010-01-12 11:00:00", "2010-01-12 12:00:00", 1.2) + +def test_mock_iss(): + response_obj = requests.models.Response() + response_obj.encoding = 'ascii' + response_obj._content = b'{"passes": [{"startUTC": 1750904990, "endUTC": 1750905545}]}' + with mock.patch('requests.get', new=mock.MagicMock(return_value=response_obj)) as mock_get: + response = iss_passes('mock_url') + assert response == [['2025-06-26 03:29:50', '2025-06-26 03:39:05']] + +@responses.activate +def test_mock_iss_resp(): + responses.add( + responses.GET, + 'https://api.n2yo.com/rest/v1/satellite/visualpasses/25544/56/0/0/5/50&apiKey=33Q884-HFUV8K-SCS3LG-55CU', + json = {"passes": [{"startUTC": 1750904990, "endUTC": 1750905545}]}, + status = 200 + ) + response = iss_passes('https://api.n2yo.com/rest/v1/satellite/visualpasses/25544/56/0/0/5/50&apiKey=33Q884-HFUV8K-SCS3LG-55CU') + assert response == [['2025-06-26 03:29:50', '2025-06-26 03:39:05']] + +# @patch.object(requests, 'get') +# def test_mock_iss(): +# response_obj = requests.models.Response() +# response_obj.encoding = 'ascii' +# response_obj._content = b'{"passes": [{"startUTC": 1750904990, "endUTC": 1750905545}]}' + \ No newline at end of file diff --git a/times.py b/times.py index d57f401..ae6c07e 100644 --- a/times.py +++ b/times.py @@ -1,9 +1,19 @@ import datetime +import requests +import json def time_range(start_time, end_time, number_of_intervals=1, gap_between_intervals_s=0): start_time_s = datetime.datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S") end_time_s = datetime.datetime.strptime(end_time, "%Y-%m-%d %H:%M:%S") + if start_time_s > end_time_s: + raise ValueError("Start time is after the end time.") + # try: + # number_of_intervals = int(number_of_intervals) + # except ValueError: + # raise ValueError('The number of intervals is not a number.') + if type(number_of_intervals) is not int and number_of_intervals > 0: + raise ValueError(f"The number of intervals is not a positive integer. You put in {number_of_intervals}!!!") d = (end_time_s - start_time_s).total_seconds() / number_of_intervals + gap_between_intervals_s * (1 / number_of_intervals - 1) sec_range = [(start_time_s + datetime.timedelta(seconds=i * d + i * gap_between_intervals_s), start_time_s + datetime.timedelta(seconds=(i + 1) * d + i * gap_between_intervals_s)) @@ -17,10 +27,26 @@ def compute_overlap_time(range1, range2): for start2, end2 in range2: low = max(start1, start2) high = min(end1, end2) - overlap_time.append((low, high)) + if high > low: + overlap_time.append((low, high)) return overlap_time +def iss_passes(url): + response=requests.get(url) + #response_text=json.loads(response.text) + response_text = response.json() + passes=response_text['passes'] + + times=[] + for p in passes: + start_unix, end_unix = p['startUTC'], p['endUTC'] + start, end = datetime.datetime.fromtimestamp(start_unix), datetime.datetime.fromtimestamp(end_unix) + times.append([start.strftime("%Y-%m-%d %H:%M:%S"),end.strftime("%Y-%m-%d %H:%M:%S")]) + return times + if __name__ == "__main__": - large = time_range("2010-01-12 10:00:00", "2010-01-12 12:00:00") - short = time_range("2010-01-12 10:30:00", "2010-01-12 10:45:00", 2, 60) - print(compute_overlap_time(large, short)) \ No newline at end of file + # large = time_range("2010-01-12 10:00:00", "2010-01-12 12:00:00") + # short = time_range("2010-01-12 10:30:00", "2010-01-12 10:45:00", 2, 60) + # print(compute_overlap_time(large, short)) + print(iss_passes('https://api.n2yo.com/rest/v1/satellite/visualpasses/25544/56/0/0/5/50&apiKey=33Q884-HFUV8K-SCS3LG-55CU')) + \ No newline at end of file diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..63def5c --- /dev/null +++ b/uv.lock @@ -0,0 +1,79 @@ +version = 1 +revision = 2 +requires-python = ">=3.11" + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "iniconfig" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, +] + +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, +] + +[[package]] +name = "pytest" +version = "8.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/08/ba/45911d754e8eba3d5a841a5ce61a65a685ff1798421ac054f85aa8747dfb/pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c", size = 1517714, upload-time = "2025-06-18T05:48:06.109Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/29/16/c8a903f4c4dffe7a12843191437d7cd8e32751d5de349d45d3fe69544e87/pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7", size = 365474, upload-time = "2025-06-18T05:48:03.955Z" }, +] + +[[package]] +name = "time-tests" +version = "0.1.0" +source = { virtual = "." } + +[package.dev-dependencies] +dev = [ + { name = "pytest" }, +] + +[package.metadata] + +[package.metadata.requires-dev] +dev = [{ name = "pytest", specifier = ">=8.4.1" }]