mirror of
https://git.zavage.net/Zavage-Software/wabot.git
synced 2026-07-22 13:36:08 -06:00
refactor: rename sessions submodule to _sessions to avoid shadowing sessions()
wabot/__init__.py defines def sessions(...) and also had a sessions.py submodule, so wabot.sessions (attribute) resolved to the function, shadowing the module for import wabot.sessions as m style access. This is the same class of collision that browser.py -> _browser.py already fixed. Renaming to _sessions.py removes the ambiguity and lets docs/api.rst drop the :no-index: Sphinx workaround in favor of plain autoclass directives on the public SessionRecord/SessionStore re-exports.
This commit is contained in:
parent
68978a34e7
commit
154344e94a
@ -16,9 +16,11 @@ API reference
|
||||
.. automodule:: wabot.pacing
|
||||
:members:
|
||||
|
||||
.. automodule:: wabot.sessions
|
||||
.. autoclass:: wabot.SessionRecord
|
||||
:members:
|
||||
|
||||
.. autoclass:: wabot.SessionStore
|
||||
:members:
|
||||
:no-index:
|
||||
|
||||
.. automodule:: wabot.hosts
|
||||
:members: ExternalServer, ManagedService, attach, service_alive
|
||||
|
||||
@ -44,7 +44,7 @@ wabot/ (repo root, branch feature/modernization
|
||||
├── src/wabot/
|
||||
│ ├── __init__.py # public API: browser(), sessions(), destroy(), re-exports
|
||||
│ ├── pacing.py # NoPacing / HumanPacing
|
||||
│ ├── sessions.py # SessionRecord, SessionStore
|
||||
│ ├── _sessions.py # SessionRecord, SessionStore (underscored to avoid shadowing sessions())
|
||||
│ ├── hosts.py # build_options, service_alive, ExternalServer,
|
||||
│ │ # ManagedService, find_driver_binary, stop_service,
|
||||
│ │ # ReattachingRemote, attach
|
||||
@ -291,10 +291,10 @@ git commit -m "feat: pacing policies (HumanPacing default behavior, NoPacing for
|
||||
```
|
||||
|
||||
---
|
||||
### Task 3: `sessions.py` — SessionRecord + SessionStore
|
||||
### Task 3: `_sessions.py` — SessionRecord + SessionStore
|
||||
|
||||
**Files:**
|
||||
- Create: `src/wabot/sessions.py`
|
||||
- Create: `src/wabot/_sessions.py`
|
||||
- Test: `tests/unit/test_sessions.py`
|
||||
|
||||
- [ ] **Step 1: Write the failing tests**
|
||||
@ -304,7 +304,7 @@ git commit -m "feat: pacing policies (HumanPacing default behavior, NoPacing for
|
||||
```python
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
from wabot.sessions import SessionRecord, SessionStore
|
||||
from wabot._sessions import SessionRecord, SessionStore
|
||||
|
||||
|
||||
def make_record(name="scraper1", created_at=None):
|
||||
@ -367,7 +367,7 @@ class TestSessionStore:
|
||||
assert store.get("scraper1") is not None
|
||||
|
||||
def test_default_path_is_under_platformdirs(self):
|
||||
from wabot.sessions import default_store_path
|
||||
from wabot._sessions import default_store_path
|
||||
|
||||
assert default_store_path().name == "sessions.json"
|
||||
assert "wabot" in str(default_store_path())
|
||||
@ -432,11 +432,11 @@ class TestSessionStore:
|
||||
- [ ] **Step 2: Run tests to verify they fail**
|
||||
|
||||
Run: `uv run pytest tests/unit/test_sessions.py -v`
|
||||
Expected: FAIL — `ModuleNotFoundError: No module named 'wabot.sessions'`
|
||||
Expected: FAIL — `ModuleNotFoundError: No module named 'wabot._sessions'`
|
||||
|
||||
- [ ] **Step 3: Write the implementation**
|
||||
|
||||
`src/wabot/sessions.py`:
|
||||
`src/wabot/_sessions.py`:
|
||||
|
||||
```python
|
||||
"""Persistence of reattachable browser sessions as plain JSON.
|
||||
@ -573,7 +573,7 @@ Expected: 14 passed
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add src/wabot/sessions.py tests/unit/test_sessions.py
|
||||
git add src/wabot/_sessions.py tests/unit/test_sessions.py
|
||||
git commit -m "feat: JSON SessionStore with stale eviction (replaces pickle persistence)"
|
||||
```
|
||||
|
||||
@ -2773,7 +2773,7 @@ from unittest.mock import MagicMock
|
||||
import pytest
|
||||
|
||||
import wabot
|
||||
from wabot.sessions import SessionRecord, SessionStore
|
||||
from wabot import SessionRecord, SessionStore
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@ -3042,7 +3042,7 @@ from .hosts import (
|
||||
)
|
||||
from .page import Page
|
||||
from .pacing import HumanPacing, NoPacing
|
||||
from .sessions import SessionRecord, SessionStore
|
||||
from ._sessions import SessionRecord, SessionStore
|
||||
|
||||
__all__ = [
|
||||
"Browser",
|
||||
@ -3282,7 +3282,7 @@ def site_url():
|
||||
|
||||
@pytest.fixture
|
||||
def store(tmp_path):
|
||||
from wabot.sessions import SessionStore
|
||||
from wabot import SessionStore
|
||||
|
||||
return SessionStore(path=tmp_path / "sessions.json")
|
||||
```
|
||||
@ -3422,7 +3422,7 @@ REATTACH_SCRIPT = textwrap.dedent(
|
||||
"""
|
||||
import json, sys
|
||||
import wabot
|
||||
from wabot.sessions import SessionStore
|
||||
from wabot import SessionStore
|
||||
|
||||
store = SessionStore(path=sys.argv[1])
|
||||
bot = wabot.browser(session=sys.argv[2], pacing=wabot.NoPacing(), store=store)
|
||||
@ -3807,7 +3807,10 @@ API reference
|
||||
.. automodule:: wabot.pacing
|
||||
:members:
|
||||
|
||||
.. automodule:: wabot.sessions
|
||||
.. autoclass:: wabot.SessionRecord
|
||||
:members:
|
||||
|
||||
.. autoclass:: wabot.SessionStore
|
||||
:members:
|
||||
|
||||
.. automodule:: wabot.hosts
|
||||
|
||||
@ -19,6 +19,7 @@ from selenium import webdriver
|
||||
from selenium.common.exceptions import WebDriverException
|
||||
|
||||
from ._browser import Browser
|
||||
from ._sessions import SessionRecord, SessionStore
|
||||
from .fields import CheckField, NullField, PageObject, SelectField, TextField
|
||||
from .hosts import (
|
||||
ExternalServer,
|
||||
@ -31,7 +32,6 @@ from .hosts import (
|
||||
)
|
||||
from .pacing import HumanPacing, NoPacing
|
||||
from .page import Page
|
||||
from .sessions import SessionRecord, SessionStore
|
||||
|
||||
__all__ = [
|
||||
"Browser",
|
||||
|
||||
@ -36,6 +36,6 @@ def site_url():
|
||||
|
||||
@pytest.fixture
|
||||
def store(tmp_path):
|
||||
from wabot.sessions import SessionStore
|
||||
from wabot import SessionStore
|
||||
|
||||
return SessionStore(path=tmp_path / "sessions.json")
|
||||
|
||||
@ -15,7 +15,7 @@ REATTACH_SCRIPT = textwrap.dedent(
|
||||
"""
|
||||
import json, sys
|
||||
import wabot
|
||||
from wabot.sessions import SessionStore
|
||||
from wabot import SessionStore
|
||||
|
||||
store = SessionStore(path=sys.argv[1])
|
||||
bot = wabot.browser(session=sys.argv[2], pacing=wabot.NoPacing(), store=store)
|
||||
|
||||
@ -3,7 +3,7 @@ from unittest.mock import MagicMock
|
||||
import pytest
|
||||
|
||||
import wabot
|
||||
from wabot.sessions import SessionRecord, SessionStore
|
||||
from wabot import SessionRecord, SessionStore
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
from wabot.sessions import SessionRecord, SessionStore
|
||||
from wabot._sessions import SessionRecord, SessionStore
|
||||
|
||||
|
||||
def make_record(name="scraper1", created_at=None):
|
||||
@ -63,7 +63,7 @@ class TestSessionStore:
|
||||
assert store.get("scraper1") is not None
|
||||
|
||||
def test_default_path_is_under_platformdirs(self):
|
||||
from wabot.sessions import default_store_path
|
||||
from wabot._sessions import default_store_path
|
||||
|
||||
assert default_store_path().name == "sessions.json"
|
||||
assert "wabot" in str(default_store_path())
|
||||
|
||||
Loading…
Reference in New Issue
Block a user