uptimer-python-sdk 0.3.0__tar.gz → 0.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/CHANGELOG.md +6 -0
  2. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/PKG-INFO +1 -1
  3. uptimer_python_sdk-0.4.0/Taskfile.yml +54 -0
  4. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/examples/06_create_rule.py +6 -0
  5. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/pyproject.toml +1 -1
  6. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/src/uptimer/__init__.py +1 -1
  7. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/src/uptimer/models/rule.py +4 -1
  8. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/tests/test_rules_endpoint.py +64 -3
  9. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/uv.lock +569 -567
  10. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/.gitignore +0 -0
  11. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/.pre-commit-config.yaml +0 -0
  12. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/.vscode/extensions.json +0 -0
  13. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/.vscode/launch.json +0 -0
  14. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/.vscode/settings.json +0 -0
  15. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/.vscode/tasks.json +0 -0
  16. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/LICENSE +0 -0
  17. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/NOTICE +0 -0
  18. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/README.md +0 -0
  19. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/examples/01_client_setup.py +0 -0
  20. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/examples/02_list_workspaces.py +0 -0
  21. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/examples/03_list_regions.py +0 -0
  22. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/examples/04_list_rules.py +0 -0
  23. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/examples/05_get_rule.py +0 -0
  24. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/examples/07_update_rule.py +0 -0
  25. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/examples/08_delete_rule.py +0 -0
  26. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/examples/README.md +0 -0
  27. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/examples/__init__.py +0 -0
  28. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/src/uptimer/client.py +0 -0
  29. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/src/uptimer/endpoints/__init__.py +0 -0
  30. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/src/uptimer/endpoints/endpoint.py +0 -0
  31. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/src/uptimer/endpoints/regions.py +0 -0
  32. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/src/uptimer/endpoints/rules.py +0 -0
  33. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/src/uptimer/endpoints/v1.py +0 -0
  34. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/src/uptimer/endpoints/workspaces.py +0 -0
  35. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/src/uptimer/errors.py +0 -0
  36. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/src/uptimer/http.py +0 -0
  37. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/src/uptimer/models/__init__.py +0 -0
  38. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/src/uptimer/models/deserialize.py +0 -0
  39. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/src/uptimer/models/errors.py +0 -0
  40. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/src/uptimer/models/region.py +0 -0
  41. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/src/uptimer/models/workspace.py +0 -0
  42. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/src/uptimer/py.typed +0 -0
  43. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/tests/__init__.py +0 -0
  44. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/tests/conftest.py +0 -0
  45. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/tests/integrations/__init__.py +0 -0
  46. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/tests/integrations/conftest.py +0 -0
  47. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/tests/integrations/test_workspaces.py +0 -0
  48. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/tests/test_client.py +0 -0
  49. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/tests/test_endpoint.py +0 -0
  50. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/tests/test_regions_endpoint.py +0 -0
  51. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/tests/test_workspaces_endpoint.py +0 -0
  52. {uptimer_python_sdk-0.3.0 → uptimer_python_sdk-0.4.0}/tools/mypy-diff.sh +0 -0
@@ -1,3 +1,9 @@
1
+ ## 0.4.0 (2026-07-15)
2
+
3
+ ### Feat
4
+
5
+ - assign regions (by name) when creating or updating a rule via `rules.create`/`rules.update`; rules now expose a `regions` field
6
+
1
7
  ## 0.3.0 (2025-08-19)
2
8
 
3
9
  ### Feat
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: uptimer-python-sdk
3
- Version: 0.3.0
3
+ Version: 0.4.0
4
4
  Summary: A Python SDK for uptimer
5
5
  Project-URL: Repository, https://github.com/myuptime-info/uptimer-python-sdk
6
6
  Author-email: Roman Zadoev <zadoev@gmail.com>
@@ -0,0 +1,54 @@
1
+ # go-task runner for the uptimer Python SDK. `task --list` shows everything.
2
+ # All tooling goes through `uv` (deps pinned by uv.lock), so local == CI.
3
+ # Release/publish flow (matches the fleet rollout — release, then publish):
4
+ # task release # cz bump (version + CHANGELOG + tag) + push
5
+ # task pypi-test # validate on TestPyPI
6
+ # task pypi # publish to PyPI (only after the release)
7
+ version: '3'
8
+
9
+ tasks:
10
+ build:
11
+ desc: Build the sdist + wheel into dist/ (uv build).
12
+ cmds:
13
+ - rm -rf dist
14
+ - uv build
15
+
16
+ test:
17
+ desc: Run the test suite (uv run pytest).
18
+ cmds:
19
+ - uv run pytest
20
+
21
+ lint:
22
+ desc: Lint + type-check (ruff + mypy).
23
+ cmds:
24
+ - uv run ruff check .
25
+ - uv run mypy src
26
+
27
+ cq:
28
+ desc: 'Code quality gate: lint + test.'
29
+ cmds:
30
+ - task: lint
31
+ - task: test
32
+
33
+ release:
34
+ desc: 'Cut a release: cq (lint + test), then `cz bump` (version + CHANGELOG + tag) + push. Commit your changes first.'
35
+ cmds:
36
+ - task: cq
37
+ - cz bump --yes
38
+ # bump commit + the tag cz just made; --follow-tags pushes only reachable tags.
39
+ - git push --follow-tags
40
+ - 'echo ">> released v$(cz version --project) — now publish with: task pypi"'
41
+
42
+ pypi-test:
43
+ desc: 'Build + upload to TestPyPI (needs a token: TWINE_USERNAME=__token__ TWINE_PASSWORD=pypi-…).'
44
+ deps: [build]
45
+ cmds:
46
+ - uv run twine check dist/*
47
+ - uv run twine upload --repository-url https://test.pypi.org/legacy/ dist/*
48
+
49
+ pypi:
50
+ desc: 'Build + upload to PyPI (needs a token). Do this only AFTER `task release`.'
51
+ deps: [build]
52
+ cmds:
53
+ - uv run twine check dist/*
54
+ - uv run twine upload dist/*
@@ -11,6 +11,10 @@ from uptimer.models.rule import (
11
11
  client = UptimerClient(api_key="your-api-key-here")
12
12
  workspace_id = "your-workspace-id-here"
13
13
 
14
+ # Regions are matched by name. List them to see what's available on your instance;
15
+ # a rule with no regions is never checked and stays at "No Data", so assign at least one.
16
+ region_names = [region.name for region in client.v1.regions.all()]
17
+
14
18
  # Create a new rule
15
19
  rule = client.v1.rules.create(
16
20
  CreateRuleRequest(
@@ -29,7 +33,9 @@ rule = client.v1.rules.create(
29
33
  body=RuleResponseBody(content="expected response"),
30
34
  kind="rule_response",
31
35
  ),
36
+ regions=region_names[:1], # assign the first available region
32
37
  ),
33
38
  )
34
39
 
35
40
  print(f"Created rule: {rule.name} (ID: {rule.id})")
41
+ print(f"Assigned regions: {rule.regions}")
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "uptimer-python-sdk"
7
- version = "0.3.0"
7
+ version = "0.4.0"
8
8
  description = "A Python SDK for uptimer"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -1,3 +1,3 @@
1
1
  """Uptimer Python SDK."""
2
2
 
3
- __version__ = "0.1.0"
3
+ __version__ = "0.4.0"
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from dataclasses import dataclass
3
+ from dataclasses import dataclass, field
4
4
 
5
5
 
6
6
  @dataclass
@@ -34,6 +34,9 @@ class BaseRule:
34
34
  workspace_id: str # workspace id
35
35
  request: RuleRequest # request configuration
36
36
  response: RuleResponse # response validation
37
+ # region names the rule runs in (matched by name). A rule with no regions is
38
+ # never checked and stays at "No Data" — assign at least one to monitor it.
39
+ regions: list[str] = field(default_factory=list)
37
40
  kind: str = "rule"
38
41
 
39
42
 
@@ -314,7 +314,7 @@ def test_create_rule(
314
314
  httpx_mock.add_response(
315
315
  method="POST",
316
316
  json=api_response(rule_result),
317
- match_content=b'{"name":"My Test Rule","interval":60,"workspace_id":"03075d25-6cad-4205-ad83-2da1bd8fad9c","request":{"url":"https://example.com","method":"GET","content_type":"application/json","data":"","kind":"rule_request"},"response":{"statuses":[200],"body":{"content":"expected response","kind":"rule_response_body"},"kind":"rule_response"},"kind":"rule"}',
317
+ match_content=b'{"name":"My Test Rule","interval":60,"workspace_id":"03075d25-6cad-4205-ad83-2da1bd8fad9c","request":{"url":"https://example.com","method":"GET","content_type":"application/json","data":"","kind":"rule_request"},"response":{"statuses":[200],"body":{"content":"expected response","kind":"rule_response_body"},"kind":"rule_response"},"regions":[],"kind":"rule"}',
318
318
  )
319
319
 
320
320
  rule_object = uptimer_client.v1.rules.create(create_request)
@@ -343,6 +343,67 @@ def test_create_rule(
343
343
  assert rule_object.response.kind == response_data["kind"]
344
344
 
345
345
 
346
+ def test_create_rule_with_regions(
347
+ uptimer_client: UptimerClient,
348
+ httpx_mock: HTTPXMock,
349
+ ):
350
+ """A rule created with regions sends them in the payload and parses them back."""
351
+ workspace_id = "03075d25-6cad-4205-ad83-2da1bd8fad9c"
352
+ rule_id = "d901834d-5768-46ae-91f5-7974b0c764b2"
353
+
354
+ create_request = CreateRuleRequest(
355
+ name="Regioned Rule",
356
+ interval=60,
357
+ workspace_id=workspace_id,
358
+ request=RuleRequest(
359
+ url="https://example.com",
360
+ method="GET",
361
+ content_type="application/json",
362
+ data="",
363
+ kind="rule_request",
364
+ ),
365
+ response=RuleResponse(
366
+ statuses=[200],
367
+ body=RuleResponseBody(content=""),
368
+ kind="rule_response",
369
+ ),
370
+ regions=["eu-west", "us-east"],
371
+ kind="rule",
372
+ )
373
+
374
+ rule_result = {
375
+ "id": rule_id,
376
+ "name": "Regioned Rule",
377
+ "interval": 60,
378
+ "workspace_id": workspace_id,
379
+ "request": {
380
+ "url": "https://example.com",
381
+ "method": "GET",
382
+ "content_type": "application/json",
383
+ "data": "",
384
+ "kind": "rule_request",
385
+ },
386
+ "response": {
387
+ "statuses": [200],
388
+ "body": {"content": "", "kind": "rule_response_body"},
389
+ "kind": "rule_response",
390
+ },
391
+ "regions": ["eu-west", "us-east"],
392
+ "kind": "rule",
393
+ }
394
+
395
+ httpx_mock.add_response(
396
+ method="POST",
397
+ json=api_response(rule_result),
398
+ match_content=b'{"name":"Regioned Rule","interval":60,"workspace_id":"03075d25-6cad-4205-ad83-2da1bd8fad9c","request":{"url":"https://example.com","method":"GET","content_type":"application/json","data":"","kind":"rule_request"},"response":{"statuses":[200],"body":{"content":"","kind":"rule_response_body"},"kind":"rule_response"},"regions":["eu-west","us-east"],"kind":"rule"}',
399
+ )
400
+
401
+ rule_object = uptimer_client.v1.rules.create(create_request)
402
+
403
+ assert rule_object.id == rule_id
404
+ assert rule_object.regions == ["eu-west", "us-east"]
405
+
406
+
346
407
  def test_update_rule_with_rule(
347
408
  uptimer_client: UptimerClient,
348
409
  httpx_mock: HTTPXMock,
@@ -398,7 +459,7 @@ def test_update_rule_with_rule(
398
459
  httpx_mock.add_response(
399
460
  method="POST",
400
461
  json=api_response(rule_result),
401
- match_content=b'{"name":"Updated Rule Name","interval":120,"workspace_id":"03075d25-6cad-4205-ad83-2da1bd8fad9c","request":{"url":"https://updated-example.com","method":"POST","content_type":"application/json","data":"{\\"key2\\": \\"value\\"}","kind":"rule_request"},"response":{"statuses":[200,201],"body":{"content":"updated expected response","kind":"rule_response_body"},"kind":"rule_response"},"kind":"rule"}',
462
+ match_content=b'{"name":"Updated Rule Name","interval":120,"workspace_id":"03075d25-6cad-4205-ad83-2da1bd8fad9c","request":{"url":"https://updated-example.com","method":"POST","content_type":"application/json","data":"{\\"key2\\": \\"value\\"}","kind":"rule_request"},"response":{"statuses":[200,201],"body":{"content":"updated expected response","kind":"rule_response_body"},"kind":"rule_response"},"regions":[],"kind":"rule"}',
402
463
  )
403
464
 
404
465
  rule_object = uptimer_client.v1.rules.update(rule_id, update_request)
@@ -481,7 +542,7 @@ def test_update_rule_with_create_request(
481
542
  httpx_mock.add_response(
482
543
  method="POST",
483
544
  json=api_response(rule_result),
484
- match_content=b'{"name":"Updated Rule Name","interval":120,"workspace_id":"03075d25-6cad-4205-ad83-2da1bd8fad9c","request":{"url":"https://updated-example.com","method":"POST","content_type":"application/json","data":"{\\"key2\\": \\"value\\"}","kind":"rule_request"},"response":{"statuses":[200,201],"body":{"content":"updated expected response","kind":"rule_response_body"},"kind":"rule_response"},"kind":"rule"}',
545
+ match_content=b'{"name":"Updated Rule Name","interval":120,"workspace_id":"03075d25-6cad-4205-ad83-2da1bd8fad9c","request":{"url":"https://updated-example.com","method":"POST","content_type":"application/json","data":"{\\"key2\\": \\"value\\"}","kind":"rule_request"},"response":{"statuses":[200,201],"body":{"content":"updated expected response","kind":"rule_response_body"},"kind":"rule_response"},"regions":[],"kind":"rule"}',
485
546
  )
486
547
 
487
548
  rule_object = uptimer_client.v1.rules.update(rule_id, update_request)