Fix SDK link, Python version contracts, test separation, token…#240
Merged
Conversation
… file permissions
- README.rst: update SDK link geotab.github.io/sdk -> developers.geotab.com;
fix docs URL to HTTPS canonical form (readthedocs.io/en/latest)
- setup.py: correct runtime guard 3.7->3.9 (typo in version + message);
add python_requires='>=3.9' for pip-level enforcement;
add mygeotab.altitude to packages list (was silently missing from installs)
- setup.cfg: remove bdist_wheel universal=1 (Python 2 artifact)
- mypy.ini: fix python_version=9 -> 3.9 (was an invalid value)
- pytest.ini: register live/integration marks; addopts skips them by default
so plain 'pytest' never needs network or credentials
- tests/test_api_live.py: apply pytestmark=pytest.mark.live
- .github/workflows/pythonpackage.yml: split single job into three:
test-offline - matrix 3.9/3.10/3.11/3.12/3.13, no secrets
test-live - unauthenticated GetVersion calls, Python 3.12
test-integration - credentialed, Python 3.12, skips if secrets absent
- mygeotab/cli.py: enforce 0700 on app config dir and 0600 on config.ini
on every write (save/logout); add logout guidance to main --help
No tests are currently marked @pytest.mark.integration, so the test-integration job collected 0 items and exited with code 5. The shell one-liner now passes when code==5 and re-raises for any other non-zero exit.
New file: - tests/test_daas_definition.py — full coverage of the previously untested daas_definition module (DaasError, DaasResult, DaasGetJobStatusResult, DaasGetQueryResult); hits all branches including the NOT_FULL_API_CALL_EXCEPTION guard, errorMessage variants, and all four has_finished() outcomes Extended: - tests/test_altitude.py — AltitudeAPI wrapper methods now tested: _extract_errors (both branches), call_api (success, invalid name, non-retry exception), create_job (success, errors, re-raise), check_job_status, wait_for_job_to_complete (immediate done, polling, error path), fetch_data (single page, not-finished guard, multi-page), get_data (combined pages, empty), do (orchestration) - tests/test_api_call.py — authentication edge cases: ExtendSession path (session_id + no password), 'ThisServer' redirect, no-path-in-result, DbUnavailableException (Initializing + UnknownDatabase), other-exception re-raise; call() re-auth when password is present, __reauthorize_count guard prevents infinite loop; multi_call with single-element (no params) - tests/test_api.py — _process() unknown-structure passthrough; _server fallback to my.geotab.com when credentials.server is None; MyGeotabException.data field - tests/test_api_entitylist.py — first/last on empty list, entity with 0 items, __add__ with plain list, __radd__, __mul__, __rmul__, __copy__, to_dataframe ImportError, entitylist.API.get return type Coverage by file (offline suite): daas_definition.py 0% → 100% exceptions.py ~90% → 100% parameters.py ~95% → 100% altitude/wrapper.py ~15% → 83% api.py ~65% → 83% ext/entitylist.py ~60% → 73% TOTAL 59% → 81%
- Drop Python 3.9 (EOL October 2025) - Add Python 3.14 (released October 2025) - setup.py: runtime guard (3,9,0)→(3,10,0); python_requires >=3.10; remove 3.9 classifier, add 3.14 classifier - mypy.ini: python_version 3.9→3.10 - pyproject.toml: ruff target-version py39→py310 - README.rst: 'Python 3.9+' → 'Python 3.10+' - CI: test-offline matrix [3.9,3.10,3.11,3.12,3.13]→[3.10,3.11,3.12,3.13,3.14]
usage.rst: - Replace all my.geotab.com/sdk/#/... links with developers.geotab.com - Fix mygeotab.api() -> mygeotab.API() (wrong case) - Fix undefined saved_session_id -> local_credentials.session_id - Fix 'a operating' -> 'an operating' - Remove stray underscore from API reference link label commandline.rst: - Remove Python 3.5.2 / Anaconda example (replace with current output) - Fix 'sesison' typo - Remove vague 'More functionality will be added' placeholder - Add security note: 0700/0600 file permissions, how to clear sessions - Add --list flag to sessions example - Add sessions --help to help section altitude.rst: - Replace broken automodule::mygeotab.altitude (empty __init__) with explicit autoclass directives for AltitudeAPI, DaasResult, DaasGetJobStatusResult, DaasGetQueryResult, DaasError - Update link from its.geotab.com to developers.geotab.com conf.py: - Replace deprecated datetime.utcnow() with datetime.now(timezone.utc)
usage.rst: - Getting Started -> /myGeotab/guides/gettingStarted/ - Concepts guide -> /myGeotab/guides/concepts/ (x2) - API methods reference -> /myGeotab/apiReference/methods/ - API objects reference -> /myGeotab/apiReference/objects/ altitude.rst: - its.geotab.com/altitude/ (308 redirect) -> altitude.geotab.com/altitude/
Source files: - api_async.py: remove stray '.abs' from call_async() docstring - exceptions.py: fix typo 'excepton' -> 'exception' in TimeoutException docs/usage.rst: - Fix 'authenticted' -> 'authenticated' - Replace nonexistent OverLimitException with correct MyGeotabException - Fix code-block language 'javascript' -> 'json' for JSON sample - Fix double 'The the' -> 'The' - Add 'Batching Calls' section documenting multi_call() - Add 'Async Usage' section with asyncio.run() example and list of all _async method variants docs/api.rst: - Switch autodoc from mygeotab.api.API (sync base) to mygeotab.api_async.API (the class actually exported at top level); async methods are now visible in the reference - Add server_call() and server_call_async() to the reference - Add intro note clarifying the exported class supports both interfaces docs/ext.rst: - Add EntityList prose section with sort_by, first/last, entity, to_dataframe() examples - Replace bare '/examples' path with GitHub hyperlink - Remove stale 'currently experimental' disclaimer docs/commandline.rst: - Document --user/-u, --password/-p, --server inline flags - State config file paths (Linux and macOS) - Document console locals (myg, mygeotab, dates) - Add IPython/ptpython enhancement note with install instructions - Remove hardcoded version number from example output docs/altitude.rst: - Add conceptual intro explaining what Altitude is and how auth works - Add Workflow section with step-by-step and do() shortcut example docs/conf.py: - Remove 2014 sphinx-quickstart comment block - Uncomment and set needs_sphinx = '7.0' (Furo/sphinx-copybutton minimum) - Rename deprecated master_doc -> root_doc (Sphinx 4.0+) - Replace placeholder Texinfo description with real one docs/index.rst: - Remove 2014 sphinx-quickstart comment block
Contributor
Author
|
@sanyamguptageotab Would you be able to review the documentation changes for the altitude.rst file? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Spring Cleaning PR
Summary
Four independent improvements to package quality, CI reliability, and security — targeting customers who begin integrations through this package.
1. SDK documentation link
https://geotab.github.io/sdk/withhttps://developers.geotab.com/readthedocs.io/en/latest)2. Python version reconciliation (3.10–3.14)
Drops Python 3.9 (EOL October 2025) and adds 3.14. Every version contract now agrees:
setup.pyruntime guard< (3, 7, 0)< (3, 10, 0)setup.pypython_requires>=3.10setup.pyclassifierssetup.pypackages listmygeotab,mygeotab.extmygeotab.altitude(was silently absent from all installs)mypy.inipython_version9(invalid)3.10pyproject.tomlrufftarget-versionpy39py310setup.cfg[bdist_wheel] universal = 1(Python 2 artifact)README.rst3. Test separation — offline vs credentialed, and full version matrix
pytest.ini — two new marks with descriptions;
addoptsexcludes both by default sopytestnever needs network access or credentials:tests/test_api_live.py —
pytestmark = pytest.mark.liveapplied..github/workflows/pythonpackage.yml — single job replaced with three:
test-offlinetest-liveGetVersioncallstest-integration4. Session token file protection
mygeotab/cli.py— enforces strict filesystem permissions on every write:os.chmod(..., stat.S_IRWXU)→ 0700 (owner only)os.chmod(..., stat.S_IRUSR | stat.S_IWUSR)→ 0600 (owner read/write only)Session.save()andSession.logout()myg --helpnow includes guidance: "To remove a saved session run:myg sessions remove <database>"5. Coverage: 59% → 81% (+22 pp)
835 lines of new tests across 5 files; 163 tests pass, 0 failures.
altitude/daas_definition.pyexceptions.pyparameters.pyaltitude/wrapper.pyapi.pyext/entitylist.pyNew file —
tests/test_daas_definition.py: full branch coverage ofDaasError,DaasResult(None/empty/missing-apiResultguards, gateway errors,apiResulterrors,"error"singular field,errorMessageas string/dict/empty),DaasGetJobStatusResult(all fourhas_finished()outcomes,errorResultoverride, missingstatuskey),DaasGetQueryResult.Extended —
tests/test_altitude.py:_extract_errors(both branches),call_api(success, invalid name, non-retry exception),create_job(success, errors in response, re-raise),check_job_status,wait_for_job_to_complete(immediate done, polling, error path),fetch_data(single page, not-finished guard, multi-page),get_data,do(full orchestration).Extended —
tests/test_api_call.py:authenticate()ExtendSessionpath,"ThisServer"redirect, no-path-in-result,DbUnavailableException(Initializing+UnknownDatabase), other-exception re-raise;call()re-auth onInvalidUserExceptionwhen password present,__reauthorize_countguard prevents infinite loop;multi_callwith no params element.Extended —
tests/test_api.py:_process()unknown-structure passthrough;_serverfallback tomy.geotab.com;MyGeotabException.datafield.Extended —
tests/test_api_entitylist.py:first/laston empty list,entitywith 0 items,__add__plain list,__radd__,__mul__/__rmul__,__copy__,to_dataframeImportError,EntityListAPI.getreturn type.Commits
6e24073chore: fix SDK link, Python version contracts, test separation, token file permissions9854eabfix(ci): treat pytest exit 5 (no integration tests) as success3c955cetest: raise offline coverage from 59% to 81%c7ee84fchore: expand supported Python range to 3.10–3.14