Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
c3789e6
chore(git): ignore more files, such as OS or IDE specific files
domi41 Apr 24, 2020
bcf575a
chore(accessibility): add extra spacing for readability to the README
domi41 Apr 24, 2020
1b2ff5a
style(github): harmonize the headers in the issue template
domi41 Apr 24, 2020
be61954
chore(PEP8)
domi41 Apr 24, 2020
d071e0a
chore(pip): add forlorn `dataclasses` to the list of python dependencies
domi41 Apr 24, 2020
1287811
chore(PEP8)
domi41 Apr 24, 2020
fcbb702
chore(PEP8)
domi41 Apr 24, 2020
8cef79a
chore(consistency)!: use plural form since it is an array
domi41 Apr 25, 2020
bf31ace
feat(features): Draft the very first scenario.
domi41 Apr 27, 2020
0088142
feat(features): add a step doing nothing for `etc.`, `…`.
domi41 Apr 27, 2020
1947ba9
feat(features): Requérir la présence à priori de citoyen⋅nes
domi41 Apr 27, 2020
14c2ff4
feat(features): implement the first two user-related steps
domi41 Apr 27, 2020
d67bdee
docs(features): document installation without Docker
domi41 Apr 27, 2020
fc63bdc
feat(features): Require polls as given
domi41 Apr 27, 2020
22b81be
chore(PEP8)
domi41 Apr 27, 2020
a40a427
config(features): don't show the clutter
domi41 Apr 27, 2020
5cb13a1
feat(feature): Count polls
domi41 Apr 27, 2020
0f9c302
feat(features): use `text2num`, found by @guhur !
domi41 Apr 27, 2020
d882dc0
docs(deatures): paint a sign
domi41 Apr 27, 2020
a7cc0ae
feat(features): add hamcrest as assertion library
domi41 Apr 27, 2020
320776e
feat(features): hook some I18N by guessing the language
domi41 Apr 27, 2020
88189ce
refacto(naming): esoteric vs exoteric steps
domi41 Apr 27, 2020
b25b062
chore(review)
domi41 Apr 27, 2020
3a62ea6
feat(features): allow `???` as dummy step
domi41 Apr 27, 2020
daf15a7
docs(features): document the ugly business with PyCharm
domi41 Apr 28, 2020
df57105
chore(features): trick the bug tracker, perhaps
domi41 Apr 28, 2020
5bf58f8
chore(features): remove fixtures code snippets
domi41 Apr 28, 2020
a64b965
feat(features): share some context between step defs
domi41 Apr 28, 2020
f2a7bf6
feat(feature): add a tool to find a user
domi41 Apr 29, 2020
3b33b0d
chore(typo)
domi41 Apr 29, 2020
ec710b8
feat(features): add a step to print the mentioned user
domi41 Apr 29, 2020
26c7dcc
feat(features): show usage example of Django test client
domi41 Apr 29, 2020
0be4c90
feat(features): add Actors
domi41 Apr 29, 2020
c79c1af
doc(features): explicit the intent of the toolbox
domi41 Apr 29, 2020
231e1f0
conf(features): Tweak behave some more.
domi41 Apr 29, 2020
0ed8c02
refacto(features): hide some more into the dbal
domi41 Apr 29, 2020
e03c703
feat(features): Print a citizen
domi41 Apr 30, 2020
576d66d
feat(features): Print a citizen
domi41 Apr 30, 2020
d612836
fix(features): use the complete locale tag, eg: `@fr_FR`
domi41 Apr 30, 2020
d8ebbba
feat(features): use localized hamcrest branch
domi41 Apr 30, 2020
85c44f2
feat(features): set the locale as well
domi41 Apr 30, 2020
c04a0f9
feat(features): implement steps about voting through the REST API
domi41 Apr 30, 2020
9aa7cb1
docs(features)
domi41 May 1, 2020
37567f9
fix(features): invert grades order, so that 0 == worst
domi41 May 2, 2020
c1a1f7b
feat(features): prepare fetching poll results
domi41 May 2, 2020
0ecdb5c
chore(PEP8)
domi41 May 2, 2020
1a44e70
feat(features): fetch poll results
domi41 May 2, 2020
9a76225
feat(urls): create a RESTful alias for fetching poll results
domi41 May 2, 2020
0586fe1
chore(features)
domi41 May 2, 2020
4c26741
Move the features out of the project.
domi41 May 16, 2020
f107b23
Ignore virtualenv files.
domi41 May 16, 2020
9933fc6
fix(behave): fix the mangling of error messages of the pretty formatter
domi41 May 17, 2020
6150f61
chore: update to fastapi
domi41 May 31, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .behaverc
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
[behave]
; We are not using the default path to leave room for unit tests ; also, apps.
paths = tests/acceptance

# What is going on? Does this change anything for you? --format=plain works
;format = plain

; Perhaps we want some of those?
;logging_clear_handlers = yes
;logging_filter = -suds

; Show all print() statements even if tests pass. (bugs! bugs!)
stderr_capture = False
stdout_capture = False
log_capture = False


show_timings = False
show_source = False
show_multiline = True
show_skipped = False
show_snippets = False
summary = True

[behave.formatters]
# We override the buggy "pretty" formatter
pretty = tests.acceptance.formatter:BeautifulFormatter
4 changes: 2 additions & 2 deletions .github/ISSUE_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

### Version

#### Expected
### Expected

#### Actual
### Actual

### Additional Details
8 changes: 6 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
*.mo
.#*

backup

# Python
__pycache__/
.mypy_cache
Expand All @@ -14,9 +12,15 @@ __pycache__/
# Local (secret) configuration
/.env.local

# Backup
backup

# Databases (dumps?)
test.db
main.db

# Operating System
.directory

# IDE
/.idea/
69 changes: 69 additions & 0 deletions INSTALL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Install

## Install using Docker

> see root README

---

## Install using virtualenv

> It's usually less painful to install using Docker instead.


### Install the required packages


#### Ubuntu & Debian


sudo apt install python3 python3-dev virtualenv
sudo apt install postgresql-server-dev-all


### Set up a virtualenv

virtualenv .venv --python=python3
source .venv/bin/activate


### Install Python dependencies

pip install -r requirements.txt


### Configure your instance

cp .env .env.local
nano .env.local
source .env.local


### Bootstrap PostgreSQL Database

sudo -u postgres psql
postgres=# ALTER USER postgres PASSWORD 'MyNotSoSecretPassword';
postgres=# CREATE DATABASE mvapi;
python manage.py migrate


### Create an Admin user

python manage.py createsuperuser


### Develop

To run each time you're setting up your shell.

source .venv/bin/activate
source env.local
python manage.py runserver

Visit http://localhost:8000/admin


### Test

python manage.py behave
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ You certainly want to apply the database migrations with:
./docker/test.sh


## Create databases migrations

sudo ./docker/makemigrations.sh


## Local development

Expand Down
4 changes: 2 additions & 2 deletions app/crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ def _check_if_ref_exists(db: Session, ref: str):


def create_election(
db: Session, election: schemas.ElectionCreate
db: Session, election: schemas.ElectionCreate,
) -> schemas.ElectionGet:
# We create first the election
# without candidates and grades
Expand All @@ -236,7 +236,7 @@ def create_election(
raise errors.InconsistentDatabaseError("Can not create election")
election_ref = str(db_election.ref)

# Then, we add separatly candidates and grades
# Then, we add separately candidates and grades
for candidate in election.candidates:
params = candidate.model_dump()
candidate = schemas.CandidateCreate(**params)
Expand Down
8 changes: 6 additions & 2 deletions app/database.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from __future__ import annotations

from contextvars import ContextVar
from urllib.parse import quote
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, declarative_base
from sqlalchemy.orm import sessionmaker, declarative_base, Session
from .settings import settings


Expand All @@ -19,7 +21,7 @@
engine = create_engine(database_url)

SessionLocal: sessionmaker = sessionmaker( # type: ignore
autocommit=False, autoflush=False, bind=engine
autocommit=False, autoflush=False, bind=engine,
)

Base = declarative_base()
Expand All @@ -31,3 +33,5 @@ def get_db():
yield db
finally:
db.close()

db_session: ContextVar[Session] = ContextVar('db_session')
2 changes: 1 addition & 1 deletion app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ async def inconsistent_database_exception_handler(
return JSONResponse(
status_code=500,
content={
"message": f"A serious error has occured with {exc.name}. {exc.details or ''}"
"message": f"A serious error has occurred with {exc.name}. {exc.details or ''}"
},
)

Expand Down
5 changes: 4 additions & 1 deletion app/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
from pydantic_settings import BaseSettings, SettingsConfigDict

class Settings(BaseSettings):
model_config = SettingsConfigDict(env_file=".env", extra="ignore")
model_config = SettingsConfigDict(
env_file=".env.local",
extra="ignore",
)

sqlite: bool = False

Expand Down
Empty file added libs/majority_judgment.py
Empty file.
Empty file added mvapi/settings.py
Empty file.
21 changes: 20 additions & 1 deletion requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,23 @@ alembic==1.8.1
types-python-jose==3.3.4
types-python-dateutil==2.8.2
mypy==1.15.0
httpx>=0.22.0
httpx>=0.22.0

# Test Runners
#nose==1.3.7
behave==1.2.6
#django-nose==1.4.6
#behave-django==1.3.0

# Assertion library
pyhamcrest==2.0.2
#git+git://github.com/domi41/PyHamcrest@hack-i18n#egg=pyhamcrest

# Test Metrics
coverage>=4.5.1

# Natural Language Processor for numbers
text2num>=2.2.0

# Markup language for humans
#PyYAML==5.3.1
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ sqlalchemy==2.0.40
pydantic==2.11.3
psycopg2==2.9.5
git+https://github.com/MieuxVoter/majority-judgment-library-python
python-jose==3.3.0
python-jose==3.4.0
python-dateutil==2.8.2
pydantic-settings==2.9.1
pydantic-settings==2.9.1
Empty file added tests/__init__.py
Empty file.
4 changes: 4 additions & 0 deletions tests/acceptance/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

Run all scenarios except the ones tagged with `@wip`:

python manage.py behave --no-skipped --tags=~@wip
Empty file added tests/acceptance/__init__.py
Empty file.
66 changes: 66 additions & 0 deletions tests/acceptance/environment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"""
Environment module for acceptance testing of the scenaristic constitution.
https://behave.readthedocs.io/en/latest/api.html#environment-file-functions
"""

from behave.runner import Context
from locale import setlocale, LC_TIME

from steps.context_main import reset_context as reset_main_context
from steps.tools_i18n import guess_locale


# Since we expect most of our step defs to require the flexibility of regular
# expressions (I18N, epicene) we make regular expressions the default.
# This is at the expense of automatic type casting of step variables.
from behave import use_step_matcher
use_step_matcher("re")
# You can still override this right before your step def if you want,
# by calling use_step_matcher() with one of the following:
# "parse" (factory default), "cfparse"
# and calling it again with "re" after your step def. (it uses a `global`)


def before_all(context: Context):
"""
Ran before the whole shooting match.
"""
pass


def before_feature(context, feature):
"""
Ran before _each_ feature file is exercised.
"""
context_locale = guess_locale(context)
setlocale(LC_TIME, "%s.UTF-8" % context_locale)
# REQUIRES CUSTOM FORK OF HAMCREST
# from hamcrest import set_locale as set_hamcrest_locale
# set_hamcrest_locale(context_locale)
##################################


def before_scenario(context, scenario):
"""
Ran before _each_ scenario is run.
"""
reset_main_context(context)
pass


def after_scenario(context, scenario):
"""
Ran after _each_ scenario is run.
"""
pass


def after_step(context, step):
"""
Ran after _each_ step is run.
"""
pass


def django_ready(context):
context.django = True
1 change: 1 addition & 0 deletions tests/acceptance/features/fr_FR
Submodule fr_FR added at 91486c
Loading