Skip to content
This repository was archived by the owner on Oct 31, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
886 commits
Select commit Hold shift + click to select a range
9733244
fixed comment in docs, thank Ali. and new docs
mdipierro May 12, 2025
24f50bf
in dashboard followlinks=True thanks tclerckx
mdipierro May 16, 2025
44bf629
fixed concatenation in grid, thanks tclerckx
mdipierro May 17, 2025
b7e0540
version 1.20250518.1
mdipierro May 19, 2025
27fe683
testing github actions
mdipierro May 19, 2025
b2df7f3
no more README.md
mdipierro May 19, 2025
94cef9e
version 1.20250518.2
mdipierro May 19, 2025
f65ce73
Message-ID in payload, thanks jpargaf
mdipierro May 20, 2025
11e7da7
style cloning and better docs, thanks tclerckx
mdipierro May 20, 2025
075eac5
reformat
mdipierro May 20, 2025
b16e4e1
Minor typos in auth.py (#973)
hzarkoob May 25, 2025
2cfd0ff
use proper strict mode (#965)
gkuznik May 25, 2025
23dc7db
use proper label for deletion checkbox (#964)
gkuznik May 25, 2025
e79bf89
Allow to check across multiple domains in URL validation (#955)
misl6 May 25, 2025
11c7204
Added missing example in CAPTCHA section (#966)
ch-rigu May 25, 2025
5fffedd
version 1.20250524.1
mdipierro May 25, 2025
33537c0
grid experimental refactor (#972)
mdipierro May 25, 2025
cefb9f1
fixed publish script
mdipierro May 25, 2025
a95a74d
fixed Grid examples
mdipierro May 25, 2025
b7b2f53
fixed search in grid
mdipierro May 26, 2025
edf78f2
experimental natural language search in grid
mdipierro May 26, 2025
ec0b034
minor cleanup
mdipierro May 26, 2025
8811149
another minor grid refactoring
mdipierro May 26, 2025
9509472
another minor grid refactoring
mdipierro May 26, 2025
b92d6de
added documentation for QueryBuilder
mdipierro May 26, 2025
c714f71
upgraded pydal to 20250526.4
mdipierro May 26, 2025
28f06e7
fixed grid bug with labels in search when labels are T
mdipierro May 27, 2025
24d1144
dbadmin using Grid and QueryBuilder
mdipierro May 27, 2025
cefbbb5
fixed user.get("past_passwords_hash", [])
mdipierro May 30, 2025
ae9fe98
Merge branch 'new-dashboard'
mdipierro Jun 1, 2025
f945148
new dashboard appadmin
mdipierro Jun 1, 2025
d3d0632
dbadmin style
mdipierro Jun 1, 2025
1a54745
dbadmin style
mdipierro Jun 1, 2025
8d1d2af
support for 'make requirements.txt'
mdipierro Jun 1, 2025
86c7f21
added grid.ActionButton
mdipierro Jun 1, 2025
0dcbbfc
fixed grid import ActionButton
mdipierro Jun 1, 2025
ab9e126
fixed row_id bug
mdipierro Jun 1, 2025
0df6695
fixed ActionButton, no more action_id
mdipierro Jun 1, 2025
c2c0c94
fixed naming of action buttons
mdipierro Jun 1, 2025
a5e0867
do not escape {} in URL(*parts)
mdipierro Jun 1, 2025
aa202ba
yet simpler grid
mdipierro Jun 1, 2025
0f2a721
fixed get_parent
mdipierro Jun 1, 2025
e1f2919
fixed style of back button in bulma etc.
mdipierro Jun 2, 2025
6dfd47e
possibly fixed ldap_plugin, thanks rakeshsingh
mdipierro Jun 4, 2025
9b4d358
possibly fixed ldap_plugin (again), thanks rakeshsingh
mdipierro Jun 4, 2025
d67f7d9
fixed uploadfield in form, thanks jpargaf
mdipierro Jun 4, 2025
18f006f
version 1.20250603.1
mdipierro Jun 4, 2025
58b6533
Grid.parse(request.query)
mdipierro Jun 5, 2025
f59a175
version 1.20250607.1, upgrades pydal to 20250607.1
mdipierro Jun 7, 2025
e73a9a2
version 1.20250607.2, upgrades pydal to 20250607.2
mdipierro Jun 7, 2025
bf6a824
version 1.20250607.3, always setup a password when installing the _da…
mdipierro Jun 8, 2025
d296eb5
fixed login required message, thanks Tom
mdipierro Jun 12, 2025
be15131
ask dashboard password at the end of setup
mdipierro Jun 12, 2025
8ddda38
minor dbadmin restyling
mdipierro Jun 12, 2025
0025dde
watchgod to watchfiles, thanks Tom
mdipierro Jun 14, 2025
c881528
watchgod to watchfiles, and better flash handling, thanks Tom
mdipierro Jun 14, 2025
86bae2c
fixed list:string in forms
mdipierro Jun 21, 2025
2bf3880
Revert "fixed list:string in forms"
mdipierro Jun 21, 2025
84b782c
restore auth in scaffold, fixes #980, thanks Nico
mdipierro Jun 21, 2025
1da1da3
DOCS: simple indentation fixes (#979)
nicozanf Jun 21, 2025
acf9484
Todo app: upgrade libs (exp. Vue3) (#977)
nicozanf Jun 21, 2025
5beee2f
howcase app: fix AttributeError with "pure html grid" example when e…
nicozanf Jun 21, 2025
58a4f42
Revert "watchgod to watchfiles, thanks Tom"
mdipierro Jun 21, 2025
ada53b2
updtade all the utils.js
mdipierro Jun 22, 2025
9f4a896
do not get variables twice
mdipierro Jun 22, 2025
8a4f21a
fixed list of string representation with and without utils.js
mdipierro Jun 22, 2025
1786aef
fixed grid
mdipierro Jun 22, 2025
63ac8d5
fixed change_password and remove test print statements
mdipierro Jun 22, 2025
0621ab2
upgraded pydal
mdipierro Jun 22, 2025
be63886
fixed grid bug **btn
mdipierro Jun 24, 2025
c3d7a6f
_Dashboard app: upgrade to Vue3 (#981)
nicozanf Jun 29, 2025
c5e3a24
Fix errorlevel set for single apps (#983)
nicozanf Jun 29, 2025
9e70982
Use f-string on _scaffold and ldap_plugin (#985)
nicozanf Jul 14, 2025
fbb321d
Better jsdoc types and ignores in utils.js (passes vscode js checking…
laundmo Jul 14, 2025
0926386
Fix login problem on Windows (#988)
nicozanf Jul 14, 2025
6600475
updated pydal 20250629.1
mdipierro Jul 14, 2025
1326e74
Add logging support to auth module and improve debug information (#989)
nicozanf Aug 3, 2025
35d3543
minor refactoring of auth logging
Aug 3, 2025
27f05d1
docs: Add Altcha captcha solution to manual (#992)
jparga Aug 13, 2025
7c25487
README: added package name to install command in venv example. Used t…
Eddiedigits Aug 19, 2025
1daca89
Removed path from code exmaples and parameter explanations. Added exp…
Eddiedigits Aug 19, 2025
1264979
removed reference to non-existane GridActionButton in chapter14
mdipierro Aug 19, 2025
b2e7174
Big form widgets refactor to allow user-defined widgets, added number…
laundmo Aug 19, 2025
025c34c
Enable Form dbio for subsets of a table, allow delaying processing (#…
laundmo Aug 19, 2025
f849d19
fix docs about db field fixture thread safety, point to the updated d…
laundmo Aug 19, 2025
53117e9
upgraded threadsafevariable, thanks laundmo
mdipierro Aug 24, 2025
426ab12
Alan Etkin's py4web blog for the spanish speaking (#997)
spametki Aug 24, 2025
258e5b0
upgraded pluralize
mdipierro Sep 1, 2025
b279482
make grid formatters_by_type always overrule field.represent for auto…
mdipierro Sep 1, 2025
99ab0f6
formatting reference fields
mdipierro Sep 1, 2025
f7114f9
fixed formatting of reference fields in grid
mdipierro Sep 1, 2025
ca0e5a3
allow unzipping from nested folders
mdipierro Sep 1, 2025
06339aa
fixed extraction of zips in _dashboard, thanks dgmanns
mdipierro Sep 3, 2025
ba34226
version 1.20250902.1
mdipierro Sep 3, 2025
3ccd161
grid changed again field.represent overrides grid.represent_by_type e…
mdipierro Sep 7, 2025
63d04d7
app update support and better error reporing in _dashboard
mdipierro Sep 8, 2025
860b200
fixed _dashboard extract deletetion of databases/uploads folders, tha…
mdipierro Sep 9, 2025
9c6399b
UTF-8 encoded file name (#998)
tyrbonit Sep 9, 2025
e933c8f
version 1.20250908.1, upgraded pydal
mdipierro Sep 9, 2025
fbec6e4
version 1.20250908.2, fixed a test
mdipierro Sep 9, 2025
ef2c87d
version 1.20250908.3
mdipierro Sep 9, 2025
0f6e3a8
new pydal 20250913.1
mdipierro Sep 13, 2025
2c6847f
upgraded pydal==20250914.1
mdipierro Sep 15, 2025
960f882
allow forms without Fields, thanks dgmanns
mdipierro Sep 15, 2025
4fa2287
allow forms without Fields (part 2), thanks dgmanns
mdipierro Sep 16, 2025
03f8500
version 1.20250915.1
mdipierro Sep 16, 2025
32c3219
use insertAdjacentText instead of insecure deprecated document.write …
laundmo Sep 18, 2025
fb2c91e
upgraded pydal to 20250920.1
mdipierro Sep 21, 2025
a1f6238
Revert "Big form widgets refactor to allow user-defined widgets, adde…
mdipierro Sep 22, 2025
d96a0ea
version 1.20250921.1
mdipierro Sep 22, 2025
3a0f90e
version 1.20250922.1, upgraded pydal to 20250922.1
mdipierro Sep 23, 2025
3b46dc7
fixed Column(represent=...), thanks Jorge
mdipierro Sep 27, 2025
65d3c68
version 1.20250926.1
mdipierro Sep 27, 2025
88d4a5c
Update core.py for double url prefix (#1002)
DavidiBeMe Oct 5, 2025
69bc417
upgraded pydal 20251012.1
mdipierro Oct 12, 2025
cf89b68
upgrade pydal to 20251012.3
mdipierro Oct 12, 2025
23becf6
version 1.20251012.1
mdipierro Oct 12, 2025
5016ac6
upgraded pydal to 20251018.1
mdipierro Oct 19, 2025
1decd41
Reapply "Big form widgets refactor to allow user-defined widgets, add…
laundmo Oct 19, 2025
8e75691
Revert "Reapply "Big form widgets refactor to allow user-defined widg…
mdipierro Oct 19, 2025
2e44f6e
fixed custom form validation, thnaks Lucas
mdipierro Nov 6, 2025
5efe9d6
ldap auth improvements (#1008)
nicozanf Nov 6, 2025
7a2693b
support Grid(search_queries=None)
mdipierro Nov 9, 2025
f417043
version 1.20251109.1
mdipierro Nov 9, 2025
05b42c6
Update index.html (#1006)
DavidiBeMe Nov 15, 2025
05d7c11
fixed the logo link in index.html, thanks David
mdipierro Nov 15, 2025
0702be3
updated Ubuntu machine-setup.sh for 24.04.03, thanks icodk
mdipierro Nov 15, 2025
2e9e07e
version 1.20251115.1
mdipierro Nov 15, 2025
707fbf2
pydal 20251207.1, thanks Kunal
mdipierro Dec 8, 2025
39534a3
added support for .py4web_ignore, thanks tclerckx
mdipierro Dec 8, 2025
e494184
handling Auth HTML emails, thanks Hadi
mdipierro Dec 8, 2025
c0dff41
version 1.20251207.1
mdipierro Dec 8, 2025
0f13fed
Possibly fixed the auto translation of messages in auth, thanks Hadi
mdipierro Dec 9, 2025
c5e6e8d
version 1.20251209.1
mdipierro Dec 10, 2025
f74ba5b
version 1.202512122025, improved file filtering, thanks tclerckx
mdipierro Dec 13, 2025
40b4f06
文档翻译为简体中文 (#1010)
Ywenzeng Dec 19, 2025
e1a00f1
Added docs/_build to gitignore and rebuilt docs
Dec 19, 2025
7ddaa75
Dashboard app - minor fixes
nicozanf Dec 27, 2025
0ea6efe
Dashboard app - follow standard structure
nicozanf Jan 5, 2026
ab0808e
upgraded pydal to v20260110.1, better handling of default validators
mdipierro Jan 10, 2026
02e6403
add Copilot instructions (#1012)
nicozanf Jan 10, 2026
51626e7
upgraded pydal to v20260110.1, better handling of default validators
mdipierro Jan 10, 2026
4b52fe8
add Copilot instructions (#1012)
nicozanf Jan 10, 2026
68a14fd
Merge branch 'nicozanf-Dashboard-1'
mdipierro Jan 10, 2026
25d117c
Revert "Dashboard app - follow standard structure"
mdipierro Jan 10, 2026
a63e500
reorganized utils.py and settings.py in dashboard
mdipierro Jan 10, 2026
6c6abfd
fixed HTML body in auth.send, thanks Hadi
mdipierro Jan 18, 2026
bb93883
Add support for .webp image format (#1013)
Pirsch Jan 18, 2026
4348916
Dashboard app: fix errors from utils and no.css (#1014)
nicozanf Jan 18, 2026
17056a5
updated start example in the docs, thanks spametki
mdipierro Jan 18, 2026
3132fce
remove undefined symbols in mailer, thanks Hadi
mdipierro Jan 18, 2026
90f6cea
upgraded pydal to v20260110.1
mdipierro Jan 18, 2026
4c8ab44
do not use cache on uv-lock
mdipierro Jan 18, 2026
c14b972
another mailing test, thanks Hadi
mdipierro Jan 18, 2026
31fc308
allow mailer to handle T types, thanks Hadi
mdipierro Jan 19, 2026
a727aa8
another mailed refactoring, thanks Hadi
mdipierro Jan 19, 2026
4cacc4b
more mailer fixes, thanks Hadi
mdipierro Jan 20, 2026
67bd0c8
version 1.20260120.1
mdipierro Jan 21, 2026
c2e2de4
fixed py4web_ignore parse issue in dashboard, thanks Tom
mdipierro Jan 24, 2026
e9c7874
Fix dropdown option visibility in dark theme, thanks Tom
mdipierro Jan 24, 2026
4b505c4
Bump wheel from 0.45.1 to 0.46.2 (#1016)
dependabot[bot] Jan 24, 2026
f8b5ddc
Dashboard app - Enhance reference fields with clickable links (#1019)
nicozanf Jan 24, 2026
2e34c6f
minor refactoring for the dashboard reference fields formatting, than…
mdipierro Jan 24, 2026
4d6584e
fixed the case of a None list of references
mdipierro Jan 24, 2026
0c2d31e
added display of reference fields in grid
mdipierro Jan 24, 2026
937ebb7
Improved logic to represent reference fields in dashboard
mdipierro Jan 25, 2026
dd673a2
Bump urllib3 from 2.5.0 to 2.6.3 (#1020)
dependabot[bot] Jan 25, 2026
3e1ab5b
fixed grid style, thanks Nico
mdipierro Jan 25, 2026
8b356c0
removed scaffold_tree.png and restored more detailed description. Tha…
mdipierro Jan 25, 2026
12d8cee
Enhanced table interface inside the dashboard (#1022)
hzarkoob Jan 27, 2026
cc66071
Moved from style info from dbadmin.html to no.css for dashboard
mdipierro Jan 27, 2026
b841840
Move the horizontal scrollbar from the table to the page body (#1023)
hzarkoob Jan 28, 2026
0f71515
Update chapter-13.rst (#1015)
ch-rigu Jan 29, 2026
5fba0ef
minor simplification in example, thanks ch-rigu
mdipierro Jan 29, 2026
e6bc89f
Improve the layout of the Details page (#1024)
hzarkoob Jan 31, 2026
f2cb78c
version 1.20260201.1
mdipierro Feb 1, 2026
b97d81d
Dashboard app: introducing themes
nicozanf Feb 7, 2026
49471d8
fixed margin
mdipierro Feb 8, 2026
3e77527
Merge branch 'nicozanf-themes'
mdipierro Feb 8, 2026
bf5bdbd
pydal 20260216.1 fixed formatting of numbers and dates
mdipierro Feb 16, 2026
892cbf0
fixed case of auth tokens without expiration, thanks rustix
mdipierro Feb 16, 2026
68ef251
various formatting issues and update uv.lock
mdipierro Feb 16, 2026
4f4c9e1
version 1.20260216.1
mdipierro Feb 16, 2026
cb30ae3
Bump cryptography from 45.0.7 to 46.0.5 (#1030)
dependabot[bot] Feb 21, 2026
0e92feb
handling strings in datetime widget
mdipierro Mar 6, 2026
20a210f
prevent traceback in reset_password
mdipierro Mar 8, 2026
30b1c7a
do not return encrypted password in forms
mdipierro Mar 8, 2026
50d109c
removed unwanted print
mdipierro Mar 8, 2026
39b002f
Bump tornado from 6.5.2 to 6.5.5 (#1034)
dependabot[bot] Mar 14, 2026
8e2bf6f
Remove unexpected blue bottom border from input elements in dark mode…
hzarkoob Mar 14, 2026
02d1984
version 1.20260313.1
mdipierro Mar 14, 2026
8761b09
many improvements (thanks claude), version 1.20260403.1
mdipierro Apr 4, 2026
07a4913
version 1.20260403.2, upgraded packages with known vulnerabilities
mdipierro Apr 4, 2026
eeadd81
Fixed lots of typos, thanks Claude
mdipierro Apr 4, 2026
333e15c
added tests, thanks Claude
mdipierro Apr 4, 2026
37c7579
rebuilt docs
mdipierro Apr 4, 2026
6631180
a first version of CLAUDE.md, there could be more here
mdipierro Apr 4, 2026
34cae1b
better claude.md
mdipierro Apr 4, 2026
4f16175
added setup_google_oauth.sh, untested
mdipierro Apr 4, 2026
d1aeee9
imrpoved scripts/setup_google_oauth.sh
mdipierro Apr 5, 2026
07140f7
Bump cryptography from 46.0.6 to 46.0.7 (#1040)
dependabot[bot] Apr 28, 2026
b369507
Bump pytest from 9.0.2 to 9.0.3 (#1041)
dependabot[bot] Apr 28, 2026
26baaed
Fix upload the file into blob field by using class Form (#1043)
ls1luke May 9, 2026
fde3bd3
added missing files
mdipierro May 9, 2026
f2bad3d
T=T for Auth, Grid, and Form
mdipierro May 9, 2026
63c12d5
Fix Cache concurrency: avoid duplicate LRU nodes on concurrent get()
mdipierro May 10, 2026
3ad07ee
Redact secret-bearing env vars in error snapshots
mdipierro May 10, 2026
8d4049f
Validate session secret with raise, not assert
mdipierro May 10, 2026
8404183
Stop accepting session token from query string
mdipierro May 10, 2026
5663ab3
Clean sys.modules on load_module failure
mdipierro May 10, 2026
d59d201
Serialise lazy-watch app reloads
mdipierro May 10, 2026
f95179e
Stop Session.__getattr__ masking AttributeError on dunder lookups
mdipierro May 10, 2026
1e0494d
Log unexpected fixture cleanup failures
mdipierro May 10, 2026
969ac06
Always XML-escape Flash class string
mdipierro May 10, 2026
3b22509
Honor use_appname=False in URL() with no parts
mdipierro May 10, 2026
553cc55
Make MetaPathRouter registration idempotent
mdipierro May 10, 2026
1f8f98b
docs(chapter-01): tighten phrasing and fix stray comma in session bullet
mdipierro May 10, 2026
367dbb1
docs(chapter-02): polish prerequisites and IDE setup sections
mdipierro May 10, 2026
87f1c22
docs(chapter-03): tighten installation guide and fix grammar/typos
mdipierro May 10, 2026
51a6fd5
docs(chapter-04): tighten Dashboard chapter wording
mdipierro May 10, 2026
41257d3
docs(chapter-05): rewrite app-creation guide for first-time readers
mdipierro May 10, 2026
d7147e3
Add IconStyleFontawesome alias for the misspelled IconStyleFontawsome
mdipierro May 10, 2026
5449baa
docs(chapter-13): align Auth chapter with current code
mdipierro May 10, 2026
45b2145
docs(chapter-12): align Form chapter with current code
mdipierro May 10, 2026
acf5e28
docs(chapter-14): align Grid chapter with current code
mdipierro May 10, 2026
4ef2664
docs: document downloader helper and Mailer usage
mdipierro May 10, 2026
6a6de81
docs(chapter-07): tighten DAL introduction prose
mdipierro May 10, 2026
f1ea01c
Add docs-pdf Make target with Pygments syntax highlighting
mdipierro May 10, 2026
3c27929
Expand contributor acknowledgements from git history
mdipierro May 10, 2026
fa392d8
fixed acknowledgements
mdipierro May 10, 2026
2c5a24e
misc fixes in apps
mdipierro May 10, 2026
420ec8b
fixed dashboard buttons alignment
mdipierro May 10, 2026
7346270
added tutorial video
mdipierro May 10, 2026
b26451a
New dashboard
mdipierro May 11, 2026
5734feb
fixed colors and icons
mdipierro May 11, 2026
9a2b8d3
improved no.css
mdipierro May 12, 2026
3a9a3e6
version 1.20260518.0, upgraded yatl, pydal, dashboard, and many small…
mdipierro May 19, 2026
bce3468
Bump urllib3 from 2.6.3 to 2.7.0 (#1044)
dependabot[bot] May 19, 2026
b76beea
Added "Customize Auth messages" section (#1045)
ch-rigu May 19, 2026
0d15984
removed hcaptcha debug prints. (#1046)
ch-rigu May 19, 2026
b525a46
version 1.20260518.1
mdipierro May 19, 2026
2daac0e
version 1.20260518.1
mdipierro May 19, 2026
94558d0
version 1.20260518.2
mdipierro May 19, 2026
a2b083a
version 1.20260519.1
mdipierro May 20, 2026
9463a87
better translations.html look in _dashboard
mdipierro May 20, 2026
4611af0
version 1.20260520.0, upgraded rocket3 and pydal
mdipierro May 21, 2026
5097da7
minor bug fixes
mdipierro May 21, 2026
60df4cd
button alignment fixes in dashboard
mdipierro May 21, 2026
1df05c3
last py4web version before the pydal refactor
mdipierro May 27, 2026
89e1048
first py4web version after the pydal refactor
mdipierro May 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
213 changes: 213 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
# PY4WEB Codebase Guide for AI Coding Agents

## Project Overview
PY4WEB is a web framework for rapid development of database-driven web applications, evolved from web2py but faster and more modern. Built on PyDAL (database abstraction layer), Ombott (WSGI framework), YATL (templating), and Renoir (template engine).

## Architecture

### Core Components
- **py4web/core.py** (2200+ lines): Central framework logic including Fixtures, action decorator, session/cache/flash, DAL integration, and CLI commands
- **py4web/__init__.py**: Exports main API (`action`, `DAL`, `Field`, `Session`, `Cache`, etc.)
- **py4web/utils/**: Modular utilities (auth, forms, grids, mailer, security, URL signing, etc.)
- **apps/**: Individual web applications following the app-per-folder convention

### Application Structure (see `apps/_scaffold/`)
Each app is a Python package with standard files:
- **__init__.py**: Imports controllers, models, settings; exposes `db` and `scheduler`; must call `py4web.check_compatible()`
- **controllers.py**: Define actions using `@action` decorator with `.uses()` for fixtures
- **models.py**: Database table definitions via PyDAL
- **common.py**: Shared fixtures (db, auth, session, cache, T, flash) instantiated here - import these, don't recreate
- **settings.py**: App configuration (DB_URI, SESSION_TYPE, VERIFY_EMAIL, etc.)
- **tasks.py**: Background scheduler tasks (PyDAL Scheduler or Celery)
- **templates/**: YATL/HTML templates
- **static/**: CSS/JS/images
- **databases/**: SQLite files and migration metadata

### Dashboard App (`apps/_dashboard/`)
Special administrative app with elevated privileges for managing py4web itself. Uses custom authentication (password file, not Auth framework) and can access/modify all app files.

**Key differences from regular apps**:
- Uses `Logged` fixture instead of `Auth` for authentication
- Can access files and databases across all applications
- Password-based login via `password.txt` file

For detailed Dashboard documentation, see `apps/_dashboard/DASHBOARD_GUIDE.md`.

## Critical Patterns

### The Fixture System
**Fixtures are the backbone** - they manage request lifecycle (db connections, sessions, templates, auth).

```python
# Correct: Declare ALL fixtures with @action.uses()
@action("index")
@action.uses(db, session, auth, T, "index.html")
def index():
return dict(message="Hello")
```

**WARNING**: Fixtures MUST be declared with `@action.uses()` or app behavior is undefined. Never mix `@action.uses()` with ActionFactory decorators (`authenticated`, `unauthenticated`).

**Fixture Lifecycle**:
1. `on_request()` - Initialize (get DB connection, load session)
2. `on_success()` or `on_error()` - Cleanup (commit/rollback DB, save session)
3. Fixtures use thread-local storage via `Fixture.local`

### Action Decorator Pattern
```python
from py4web import action, request, redirect, URL
from .common import db, session, auth, T

@action("path/to/endpoint") # Routes to /{app_name}/path/to/endpoint
@action.uses(db, session, auth.user, T, "template.html")
def my_action():
# auth.user requires logged-in user (raises HTTP 401 if not)
user = auth.get_user()
# Return dict for templates, or direct response
return dict(data=db(db.table).select())
```

### Database (PyDAL) Integration
```python
# In models.py - define tables
from .common import db, Field
from pydal.validators import IS_NOT_EMPTY, IS_EMAIL

db.define_table('person',
Field('name', requires=IS_NOT_EMPTY()),
Field('email', requires=IS_EMAIL()))
db.commit() # Always commit models

# In controllers.py - query data
@action("list")
@action.uses(db, "list.html")
def list_people():
rows = db(db.person).select()
return dict(rows=rows)
```

**Thread-Safety**: PyDAL Field attributes (`readable`, `writable`, `default`, `requires`, etc.) are ThreadSafeVariable - safe to modify per-request.

### Authentication Flow
Auth is configured in `common.py`. Standard pattern:
```python
from py4web.utils.auth import Auth

auth = Auth(session, db, define_tables=False)
auth.use_username = True
auth.param.registration_requires_confirmation = settings.VERIFY_EMAIL
# Auth defines tables on first use
auth.enable() # Call in common.py to create auth_user, auth_group tables
```

Use fixtures: `auth` (any user), `auth.user` (logged-in only).

## Developer Workflows

### Setup & Run
```bash
# Standard installation
pip install --upgrade py4web
py4web setup apps # Creates app scaffolds, sets dashboard password
py4web run apps # Runs on localhost:8000

# With uv (recommended)
uv run --with py4web python 3.12 py4web setup apps
uv run --with py4web python 3.12 py4web run apps

# Development with auto-reload
py4web run -p password.txt apps --watch=lazy -L20 # -L20 = INFO logging
```

### Testing
```bash
uv run --python 3.13 --extra test pytest --cov=py4web --cov-report html:cov.html -v tests/
```

Tests are in `tests/` using pytest. See `tests/test_action.py` for action/fixture testing patterns.

### Creating New Apps
```bash
py4web new_app -s apps/myapp # -s uses _scaffold template
```

Or copy `apps/_scaffold/` manually. Must import controllers in `__init__.py` to expose actions.

### CLI Commands
```bash
py4web setup apps # Interactive app creation wizard
py4web set_password # Set dashboard password
py4web run apps # Start server
py4web shell apps # Python shell with apps loaded
py4web routes apps # Show all registered routes
py4web version # Show version
```

See `py4web/core.py` lines 1941-2241 for CLI implementation.

## Project Conventions

### Import Patterns
```python
# In controllers.py
from py4web import action, request, response, redirect, abort, URL
from .common import db, session, auth, T, cache, flash # Shared fixtures
from yatl.helpers import A, DIV, SPAN # HTML helpers
```

Never instantiate fixtures in controllers - import from `common.py`.

### URL Generation
```python
# In controllers
URL('other_action', vars=dict(id=123))
# In templates
[[=URL('action', vars=dict(x=1))]] # [[ ]] delimiters for YATL
```

### Template Syntax (YATL)
- Delimiters: `[[ python code ]]`
- Helpers auto-imported: `A`, `DIV`, `TABLE`, etc.
- Context: `request`, `URL`, `__vars__` (returned dict) available

### Session Types
Configured via `settings.SESSION_TYPE`:
- `"cookies"` - Client-side (default, good for most)
- `"database"` - Server-side in DB (requires `DBStore`)
- `"redis"` - Server-side in Redis
- `"memcache"` - Server-side in Memcache

### Background Tasks
PyDAL Scheduler (default) or Celery. In `tasks.py`:
```python
from .common import scheduler

def my_task(inputs):
# Task logic
pass

scheduler.register_task("my_task", my_task)
scheduler.enqueue_run("my_task", inputs={}, period=60)
```

## Key Files Reference
- **py4web.py**: Entry point, calls `py4web.core.cli()`
- **pyproject.toml**: Dependencies (pydal, ombott, renoir, yatl, etc.), version in `py4web.__init__.__version__`
- **Makefile**: Build/test commands (`make test`, `make assets`, `make docs`)
- **apps/_scaffold/**: Template for new apps - study this for patterns
- **apps/_dashboard/**: Web-based admin interface (edit code, manage DB)

## Common Pitfalls
1. **Forgetting `@action.uses()`** - Always declare fixtures or db connections won't work
2. **Creating fixtures in controllers** - Import from `common.py`, don't instantiate
3. **Not committing models** - Always `db.commit()` at end of `models.py`
4. **Mixing action styles** - Don't mix `@action`/`@action.uses()` with ActionFactory decorators
5. **Wrong app loading** - Apps must import controllers in `__init__.py` to register actions

## External Resources
- Main website: https://py4web.com
- Documentation: https://py4web.com/_documentation
- GitHub: https://github.com/web2py/py4web
- Mailing List: https://groups.google.com/g/py4web
- Discord: https://discord.gg/xCzQ9KTk3W
- PyDAL docs: https://py4web.com/_documentation/static/en/chapter-07.html
28 changes: 9 additions & 19 deletions .github/workflows/run_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
push:
branches:
- master
- ombott-dev
pull_request:
branches:
- master
Expand All @@ -14,24 +15,13 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.7, 3.8, 3.9]
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]

env:
UV_PYTHON: ${{ matrix.python-version }}
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
sudo apt-get install memcached libmemcached-tools
python -m pip install --upgrade pip
python3 -m pip install -r requirements.txt
python3 -m pip install -r test-requirements.txt
- name: build
run: |
python3 setup.py install
- name: Test with pytest
run: |
python3 -m pytest --cov=py4web --cov-report html:cov.html -v -s tests/

- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v5
- name: Test
run: make test
16 changes: 11 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*.1
*.bak
*.bak2
.envrc
*.svn
*.w2p
*.class
Expand All @@ -17,22 +18,23 @@ Thumbs.db
./build
./dist
./ssl
./docs
./logs
./*.zip
docs/_build
requirements.txt
apps/_documentation/static/*/*.pdf
apps/_documentation/static/*/*.epub
apps/*
apps*/*/*
!apps/todo/*
!apps/examples/*
!apps/showcase/*
!apps/_dashboard/*
!apps/_scaffold/*
!apps/_minimal/*
!apps/_websocket/*
!apps/_default/*
!apps/_documentation/*
!apps/superheroes/*
!apps/myfeed/*
!apps/fadebook/*
apps/*/databases/*
apps/*/uploads/*
**/*.py[co]
Expand All @@ -43,6 +45,10 @@ deployment_tools/gae/lib
deployment_tools/gae/apps
deployment_tools/gae/requirements.txt
py4web/assets
pyproject.toml
poetry.lock
workspace.code-workspace
venv
docs/_build
py4web.egg-info/
build/
tmp/
12 changes: 0 additions & 12 deletions .travis.yml

This file was deleted.

24 changes: 24 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: py4web",
"type": "python",
"request": "launch",
"program": "py4web.py",
"args": [
"run", "--errorlog=:stdout", "-L", "20",
"apps"
],
"console": "integratedTerminal",
"justMyCode": true
},
{
"name": "Python: File",
"type": "python",
"request": "launch",
"program": "${file}",
"justMyCode": true
}
]
}
Loading