repository (nest_backend.database.tables.Authorization attributo)

repository_id (nest_backend.database.tables.Condition attributo)

evaluation_mode (nest_backend.database.tables.Repository attributo)

authorizations (nest_backend.database.tables.Repository attributo)

coordinates (nest_backend.database.tables.ConditionType attributo)

Scrivere le conclusioni.

    "cosa avete imparato, cosa è andato bene, cosa cambiereste"

Descrivere genericamente il processo di sviluppo seguito, includendo:

    "numero e durata degli sprint, burndown complessivo, diari dei partecipanti e/o diario di gruppo,
    retrospettiva finale"

Visto che i diari e la retrospettiva li abbiamo già altrove, suggerirei di metterci solo un link usando ``:ref:``.

"numero e durata degli sprint, burndown complessivo, diari dei partecipanti e/o diario di gruppo,
retrospettiva finale"

«numero e durata degli sprint, burndown complessivo, diari dei partecipanti e/o diario di gruppo,
retrospettiva finale»

Visto che i diari e la retrospettiva li abbiamo già altrove, suggerirei di metterci solo un link usando 

Inserire informazioni generali sullo sprint, come inizio e fine.

Questa statistica è stata generata dal prof. Marcello Missiroli con
`Gitinspector`_ al termine dello Sprint.

La seguente documentazione è stata fornita dal cliente durante questo sprint:

Stesura documenti Sprint 1 (debito tecnico e relazione sprint retrospective), realizzazione video Sprint1 review

Per il lavoro di testing è stata utilizzata anche la tecnica del Pair Programming, grazie ad un plugin dell'IDE utilizzato.

Per il lavoro di testing è stata utilizzata anche la tecnica del Pair Programming, grazie ad un plugin dell’IDE utilizzato.

Studio del backend, volto a capire il funzionamento delle varie API

Testing login e retrieval dei dati inerenti a tutti gli utenti registrati

Test cancellazione utente e ritorno dei dati inerenti a quell’utente

Testing ritorno di tutte le repository di proprietà dell’utente loggato, ritorno delle info inerenti alla repository specificata

Testing modifica ed eliminazione di una repository (nome, stato)

Testing del frontend tramite UI, controllo generale dei test già effettuati.

Durante lo sprint ho principalmente svolto sviluppo e test riguardo alla API di twitter, in modo da poter effettuare chiamate efficenti e non venire limitati dal sito riguardo alle richieste effettuate.

Definizione di entita' di esempio nei database per provare funzioni legate ad esse

Definizione di entita” di esempio nei database per provare funzioni legate ad esse

Definizione di funzioni per l'aggregazione di condizioni di diverso tipo per la ricerca di tweet tramite API

Definizione di funzioni per l’aggregazione di condizioni di diverso tipo per la ricerca di tweet tramite API

Refactor codice scritto fino a quel momento, eliminazione di dati inutili

Implementazioni di analisi su termini e hashtag restituiti dall'API

Implementazioni di analisi su termini e hashtag restituiti dall’API

Test di chiamata alle funzioni di ricerca a partire da repository con condizioni complesse aggregate

Incontro con SM e PO per valutare quali US andranno nello sprint2

Ritorno alla versione 1.1 perche' lascia disponibili le query sulla geolocalizzazione gratuitamente

Ritorno alla versione 1.1 perche” lascia disponibili le query sulla geolocalizzazione gratuitamente

Il prof. Marcello Missiroli non ha ancora generato la statistica dello Sprint 3.

Inserire qui uno screenshot della schermata finale di SonarQube.

Scrivere una guida all'installazione di un servizio SystemD per il crawler.

Scrivere una guida all’installazione di un servizio SystemD per il crawler.

Questa guida illustra come installare interamente N.E.S.T. su un server Linux.

Un sistema operativo Linux-based (preferibilmente `Arch Linux <https://wiki.archlinux.org/title/Main_page>`_)

`SystemD ^248.2 <https://www.freedesktop.org/wiki/Software/systemd/>`_

Per motivi di sicurezza, si suggerisce di creare un nuovo utente con il quale eseguire il progetto:

È necessario essere amministratori di sistema per eseguire i seguenti comandi.
Si veda il manuale di `useradd <https://linux.die.net/man/8/useradd>`_ per più dettagli.

Si veda il manuale di 

root:~# mkdir --parents /srv/nest
root:~# useradd --home-dir /srv/nest --shell /bin/bash nest
root:~# chown --recursive nest: /srv/nest

Per installare N.E.S.T., è necessario avere il codice sorgente disponibile sul server.

Questo creerà una nuova cartella ``g2-progetto`` nella directory in cui è stato eseguito il comando.

N.E.S.T. necessita di un database PostgreSQL in cui salvare i dati.

Per motivi di sicurezza, si suggerisce di creare un ruolo isolato dal resto del DBMS apposta per N.E.S.T.:

Il backend usa un file di configurazione per impostare alcune variabili.

Si crei un nuovo file nella working directory del progetto denominato ``config.py``:

Si crei un nuovo file nella working directory del progetto denominato 

# Una stringa rappresentante il database da utilizzare
# Per maggiori informazioni sulla sintassi, si veda https://docs.sqlalchemy.org/en/14/core/engines.html
SQLALCHEMY_DATABASE_URI = "postgresql://nest@/nest"

# Una stringa casuale utilizzata per generare i JSON Web Token (JWT)
# Va mantenuta segreta e costante per tutta l'operazione del backend!
# Si suggerisce di premere tasti casuali sulla tastiera finchè la riga non è piena.
SECRET_KEY = "dsjiofgvinmodfiojvbnio3erfnoiweraqugu43ghjwrevniuwerng43iugnreuwignhritmj43i43nb8i42ug0wevkwovmwigtjj"

Le dipendenze Python sono gestite da *Poetry*, e possono essere installate con:

Poetry creerà automaticamente un `venv <https://docs.python.org/3/library/venv.html>`_ e vi installerà all'interno tutti
i pacchetti necessari all'esecuzione del backend e del crawler di N.E.S.T. .

 e vi installerà all’interno tutti
i pacchetti necessari all’esecuzione del backend e del crawler di N.E.S.T. .

 e vi installerà all'interno tutti

**Si suggerisce di ricordare il nome del venv creato da Poetry**, in quanto sarà necessario per
:ref:`Creare un servizio SystemD per il backend`:

**Si suggerisce di ricordare il nome del venv creato da Poetry**

Creating virtualenv nest-7C2fm2VD-py3.9 in /srv/nest/.cache/pypoetry/virtualenvs

Le dipendenze NodeJS sono gestite da *npm*, e possono essere installate con:

npm creerà automaticamente una cartella
`node_modules <https://docs.npmjs.com/cli/v7/configuring-npm/folders#node-modules>`_ e vi installerà all'interno tutte
le librerie necessarie all'esecuzione del frontend di N.E.S.T. .

 e vi installerà all’interno tutte
le librerie necessarie all’esecuzione del frontend di N.E.S.T. .

 e vi installerà all'interno tutte

Per fare in modo che il backend rimanga attivo in background, anche dopo un riavvio, si suggerisce di installarlo come
servizio di sistema di *SystemD*:

servizio di sistema di 

[Unit]
Description=N.E.S.T. Backend
Wants=network-online.target postgresql.service
After=network-online.target nss-lookup.target postgresql.service

[Service]
Type=exec
User=nest
Group=nest
WorkingDirectory=/srv/nest/g2-progetto

# Si sostituisca a questo il percorso del virtualenv creato in precedenza da Poetry
#         ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
ExecStart=/srv/nest/.cache/pypoetry/virtualenvs/nest-7C2fm2VD-py3.9/bin/python -m gunicorn -b 127.0.0.1:30040 --env="FLASK_CONFIG=../config.py" nest_backend.app:rp_app

[Install]
WantedBy=multi-user.target

Ora, si verifichi che il servizio si avvii correttamente eseguendolo manualmente con:

In caso di successo, l'API dovrebbe essere esposto sulla porta ``30040`` dell'indirizzo di loopback ``127.0.0.1``:

root:~# curl 127.0.0.1:30040/doa
If you see this, the server is fine.

Si abiliti il servizio, in modo che venga automaticamente avviato al riavvio del sistema:

Perchè sia possibile servire il frontend agli utenti, è necessario prima crearne una versione compilata ottimizzata.

Verrà creata una cartella ``build`` con all'interno la versione compilata.

Per rendere disponibile alla rete la copia locale del frontend, si suggerisce di avviare lo script npm ``serve``
integrato con N.E.S.T. come un servizio di sistema di *SystemD*:

Per rendere disponibile alla rete la copia locale del frontend, si suggerisce di avviare lo script npm 

[Unit]
Description=N.E.S.T. Frontend
Wants=network-online.target nest-backend.service
After=network-online.target nss-lookup.target nest-backend.service

[Service]
Type=exec
Environment=NODE_ENV=production
User=nest
ExecStart=/usr/bin/npm run serve

[Install]

Questo file non è stato testato, in quanto sul server demo è in uso una versione più complessa che usa
`nvm <https://github.com/nvm-sh/nvm>`_ per gestire più versioni di NodeJS sullo stesso sistema.

La versione in uso sul server demo è:

.. code-block:: systemd

    [Unit]
    Description=N.E.S.T. Frontend
    Wants=network-online.target nest-backend.service
    After=network-online.target nss-lookup.target nest-backend.service

    [Service]
    Type=exec
    Environment=NODE_ENV=production
    Environment=NODE_VERSION=16
    User=nest
    Group=nest
    WorkingDirectory=/srv/nest/g2-progetto
    ExecStart=/srv/nest/.nvm/nvm-exec npm run serve

    [Install]
    WantedBy=multi-user.target

[Unit]

[Service]
Type=exec
Environment=NODE_VERSION=16
User=nest
ExecStart=/srv/nest/.nvm/nvm-exec npm run serve

[Install]

In caso di successo, il frontend dovrebbe essere esposto sulla porta ``30041`` dell'indirizzo di loopback ``127.0.0.1``:

In caso di successo, il frontend dovrebbe essere esposto sulla porta 

Scrivere una guida all'esecuzione ripetuta del crawler attraverso un timer SystemD.

Scrivere una guida all’esecuzione ripetuta del crawler attraverso un timer SystemD.

Per rendere l'API e il frontend disponibili al pubblico, si suggerisce di configurare Apache HTTP Server
come reverse proxy.

Per rendere l’API e il frontend disponibili al pubblico, si suggerisce di configurare Apache HTTP Server

La configurazione di Apache varia molto da distribuzione a distribuzione Linux, e talvolta anche da server a server;
pertanto, si fornisce solamente un file `VirtualHost <https://httpd.apache.org/docs/2.4/vhosts/examples.html>`_ di
esempio da adattare al proprio setup:

pertanto, si fornisce solamente un file 

<VirtualHost *:80>
    ServerName "api.nest.steffo.eu"
    ServerName "prod.nest.steffo.eu"

    RewriteEngine On
    RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]
</VirtualHost>

<VirtualHost *:443>

    SSLEngine on
    SSLCertificateFile      "/root/.acme.sh/*.nest.steffo.eu/fullchain.cer"
    SSLCertificateKeyFile   "/root/.acme.sh/*.nest.steffo.eu/*.nest.steffo.eu.key"

    ProxyPass           "/" "http://127.0.0.1:30040/"
    ProxyPassReverse    "/" "http://127.0.0.1:30040/"
    RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}

    Protocols h2 http/1.1
    Header always set Strict-Transport-Security "max-age=63072000"

    ProxyPass           "/" "http://127.0.0.1:30041/"
    ProxyPassReverse    "/" "http://127.0.0.1:30041/"

No directive entry for "warning" in module "docutils.parsers.rst.languages.it".
Using English fallback for directive "warning".

No directive entry for «warning» in module «docutils.parsers.rst.languages.it».
Using English fallback for directive «warning».

Il team ha definito lo stato di Ready di una User Story in base ai seguenti criteri:

Il Product Owner ha la visione necessaria per definirne la priorità

La User Story è indipendente o dipendente da altre a priorità maggiore

La definizione di Done è stata concordata da tutto il team con il Product Owner, ed è stata così
definita:

mockup UI con relativo css (creazione componenti, light/dark mode)

Giovanni ha iniziato a raccogliere dati sul tempo impiegato a partire dallo Sprint 1.

Giorgio ha iniziato a raccogliere dati sul tempo impiegato a partire dallo Sprint 1.

Lorenzo ha iniziato a raccogliere dati sul tempo impiegato a partire dallo Sprint 1.

:Goal: Learn
:Question: Do team members understand the Scrum roles?
:Metric: Knowledge of Scrum roles by questions
:Evaluation: :1: no idea of the Scrum roles
             :5: perfect knowledge of the roles and their jobs
:Chiara: 4
:Giorgio: 4
:Giovanni: 4
:Stefano P.: 4
:Lorenzo: 5
:Stefano G.: 5
:Flavia: 4

:1: no idea of the Scrum roles
:5: perfect knowledge of the roles and their jobs

:Question: Do team members feel they learned the process?
:Metric: Opinions from the participants
:Evaluation: :1: couldn't repeat the game
             :5: could play the game as a Scrum Master by himself
:Chiara: 3
:Giorgio: 3
:Stefano P.: 5
:Lorenzo: 3
:Stefano G.: 3
:Flavia: 3

:1: couldn't repeat the game
:5: could play the game as a Scrum Master by himself

:Question: Does everyone keep up with the other players?
:Metric: Check during every sprint retrospective if every one is on point
:Evaluation: :1: totally lost
             :5: leads the game driving the other players
:Chiara: 3
:Flavia: 5

Check during every sprint retrospective if every one is on point

:Goal: Practice
:Question: Are the game mechanics linear and repeatable?
:Evaluation: :1: feels the game is unrepeatable
             :5: feels the game could be played in any situation
:Chiara: 1
:Giorgio: 2
:Giovanni: 1
:Stefano P.: 1
:Lorenzo: 1
:Stefano G.: 2
:Flavia: 1

:1: feels the game is unrepeatable
:5: feels the game could be played in any situation

:Question: Do team success in completing the game?
:Metric: Number of User Stories completed
:Evaluation: :1: 0 to 3 stories
             :2: 4 to 6
             :3: 7 to 9
             :4: 10 to 12
             :5: 13 to 15
:Chiara: 5
:Giorgio: 5
:Giovanni: 5
:Flavia: 5

:1: 0 to 3 stories
:2: 4 to 6
:3: 7 to 9
:4: 10 to 12
:5: 13 to 15

:Question: Do team members efficiently estimate during sprint planning?
:Metric: Uniformity in evaluating the size and the priority of user stories
:Evaluation: :1: abnormal difference from the other players
             :5: coherent and uniform with the group most of the time
:Chiara: 5

Uniformity in evaluating the size and the priority of user stories

:1: abnormal difference from the other players
:5: coherent and uniform with the group most of the time

:Goal: Cooperation
:Question: Do team members know each other better?
:Metric: Level of players' serenity throughout the game
:Evaluation: :1: never speaks with the other players
             :5: talks friendly to anyone in every situation
:Chiara: 4
:Flavia: 4

:1: never speaks with the other players
:5: talks friendly to anyone in every situation

:Question: Does the game let all players cooperate?
:Metric: Contribution of every player during the game
:Evaluation: :1: never puts effort in doing something
             :5: every time is willing to understand what is going on
:Chiara: 4
:Giovanni: 3
:Stefano P.: 2
:Stefano G.: 4
:Flavia: 3

:1: never puts effort in doing something
:5: every time is willing to understand what is going on

:Question: Do team member consult each other about a topic?
:Metric: Sharing of ideas
:Evaluation: :1: never asks for an opinion
             :5: wants to discuss about every topic
:Chiara: 5
:Stefano P.: 3
:Flavia: 5

:1: never asks for an opinion
:5: wants to discuss about every topic

:Goal: Motivation
:Question: Do team members encourage collegues in need?
:Metric: Players explain something other players don't understand
:Evaluation: :1: not involved by the game
             :5: always makes sure everyone is on point
:Chiara: 3
:Flavia: 4

:1: not involved by the game
:5: always makes sure everyone is on point

:Question: Does PO help the team?
:Metric: Quality of PO's advices to get better in the next sprints
:Evaluation: :1: poor/absent advices
             :5: wise and helpful suggestions when is required

:1: poor/absent advices
:5: wise and helpful suggestions when is required

:Question: Does the team come up with good ideas?
:Metric: Effectiveness of sprint retrospective
:Evaluation: :1: doesn't express opinions during retrospective
             :5: feels the retrospective fundamental to express opinions
:Chiara: 4
:Flavia: 5

:1: doesn't express opinions during retrospective
:5: feels the retrospective fundamental to express opinions

:Goal: Problem Solving
:Question: Do team members behave well when facing a problem?
:Metric: Level of the technical debt at the end of the game
:Evaluation: On the game board, if the debt pawn is on the lowest stage,the evaluation is 5, for every higher stage it decreases by 1
:Chiara: 5
:Flavia: 5

On the game board, if the debt pawn is on the lowest stage,the evaluation is 5, for every higher stage it decreases by 1

:Question: Does team organize their tasks properly?
:Metric: Average of tasks left at the end of each sprint
:Evaluation: :1: 21+ average tasks left
             :2: 16-20 average tasks left
             :3: 11-15 average tasks left
             :4: 6-10 average tasks left
             :5: 0-5 average tasks left
:Chiara: 5

:1: 21+ average tasks left
:2: 16-20 average tasks left
:3: 11-15 average tasks left
:4: 6-10 average tasks left
:5: 0-5 average tasks left

:Question: Does PO plan efficiently the Sprint Backlog?

L'obiettivo del progetto è la creazione di un software per fornire l'aggregazione e l'analisi di `Tweet`_, in modo da
rilevare eventi *macroscopici*, *locali* o più semplicemente filtrarli in base a delle *keyword*.

L’obiettivo del progetto è la creazione di un software per fornire l’aggregazione e l’analisi di 

L'obiettivo del progetto è la creazione di un software per fornire l'aggregazione e l'analisi di 

Il prodotto sarà utilizzato dal cliente e da un piccolo gruppo di suoi dipendenti per effettuare ricerche statistiche.

Il software andrà ad integrarsi direttamente con `Twitter`_, da cui verranno raccolti dati e su cui verranno pubblicate
allerte su di essi.

, da cui verranno raccolti dati e su cui verranno pubblicate

Il software permetterà di selezionare **condizioni** con cui scegliere quali tweet raccogliere:

Selezionate le condizioni, l'utente potrà creare una **repository**: una cartella in cui verranno raccolti i tweet
soddisfacenti le condizioni richieste.

: una cartella in cui verranno raccolti i tweet

Una volta raccolti, i tweet di una repository potranno essere **analizzati** in qualsiasi momento: durante l'analisi,
saranno mostrate statistiche e grafici relativi ai tweet.

 in qualsiasi momento: durante l’analisi,

 in qualsiasi momento: durante l'analisi,

La raccolta potrà essere interrotta in qualsiasi momento **archiviando** il repository.

Sarà possibile **condividere** una repository con altri utenti della piattaforma, permettendo loro di analizzarla.

 una repository con altri utenti della piattaforma, permettendo loro di analizzarla.

Infine, l'utente potrà configurare una repository in modo che gli invii una **allerta** qualora vengano raccolti un dato
numero di tweet in una certa *finestra temporale*.

Infine, l’utente potrà configurare una repository in modo che gli invii una 

Infine, l'utente potrà configurare una repository in modo che gli invii una 

.. _hashtag: https://help.twitter.com/it/using-twitter/how-to-use-hashtags

.. _posizione geografica: https://help.twitter.com/en/safety-and-security/tweet-location-settings

Il software trova utilizzo principalmente in **ambito statistico**, essendo il suo scopo quello di raccogliere dati e
permettere di analizzarli tramite un'interfaccia grafica.

, essendo il suo scopo quello di raccogliere dati e
permettere di analizzarli tramite un’interfaccia grafica.

Il software potrà essere utilizzato da utenti con una discreta esperienza nell'analisi di dati ma senza particolari
conoscenze informatiche.

Il software potrà essere utilizzato da utenti con una discreta esperienza nell’analisi di dati ma senza particolari

Repository
Raccolta di tweet che soddisfano determinate condizioni.

Condizione
Predicato logico che deve essere soddisfatto da un tweet per essere raccolto in fase di raccolta dati, o per essere
contato in fase di allertamento utente.

Filtro
Predicato logico che deve essere soddisfatto da un tweet per essere visualizzato in fase di analisi dati.

Allarme
Notifica inviata all'utente attraverso un mezzo telematico, come email oppure un tweet.

Notifica inviata all’utente attraverso un mezzo telematico, come email oppure un tweet.

Utente
Utilizzatore del software con un proprio account creato dall'amministratore della piattaforma.

In particolare, la piattaforma prevederà due tipologie di utenti:

Utente regolare
    Potranno eseguire attività di creazione, analisi, condivisione, archiviazione ed eliminazione dei propri repository.

Utente amministratore
    Potrà effettuare tutte le attività dell'utente regolare, e in aggiunta potrà creare ed eliminare nuovi utenti
    regolari.

Utilizzatore del software con un proprio account creato dall’amministratore della piattaforma.

Potranno eseguire attività di creazione, analisi, condivisione, archiviazione ed eliminazione dei propri repository.

Potrà effettuare tutte le attività dell'utente regolare, e in aggiunta potrà creare ed eliminare nuovi utenti
regolari.

regolari.

Potrà effettuare tutte le attività dell’utente regolare, e in aggiunta potrà creare ed eliminare nuovi utenti
regolari.

Estendere il glossario qualora vengano incontrati altri termini.

N.E.S.T. prevede tre tipologie di *agenti* ("utenti" UML): **utente**, **amministratore** e **sistema**.

I principali casi d’uso individuati durante la progettazione di N.E.S.T. sono:

La gestione degli utenti da parte di un Amministratore:

.. image:: CasiUso1.PNG
    :width: 400

La gestione del login da parte di un Utente:

.. image:: CasiUso2.PNG

La gestione delle Allerte sia dal punto di vista dell’Utente che del Sistema:

.. image:: CasiUso3.PNG
    :width: 800

La gestione della raccolta da parte dell'utente:

.. image:: CasiUso4.PNG

La gestione di un repository da parte dell'utente:

.. image:: CasiUso5.PNG

La visualizzazione di un repository:

.. image:: CasiUso6.PNG

Si riporta qui di seguito il Backlog definito ad inizio progetto, prima dell’avvio dello sviluppo.
Gli elementi dal bordo grigio sono le epiche:

Alcune user story sono state rimosse in seguito al feedback ricevuto durante il primo sprint!

No directive entry for "image" in module "docutils.parsers.rst.languages.it".
Using English fallback for directive "image".

No directive entry for «image» in module «docutils.parsers.rst.languages.it».
Using English fallback for directive «image».

No directive entry for "note" in module "docutils.parsers.rst.languages.it".
Using English fallback for directive "note".

No directive entry for «note» in module «docutils.parsers.rst.languages.it».
Using English fallback for directive «note».

ZERO-CLAUSE BSD LICENSE FOR CODE IN THE PYTHON 3.8.10 DOCUMENTATION

email.message.Message: Representing an email message using the compat32 API

What is the most efficient way to concatenate many strings together?

Why does a_tuple[i] += [‘item’] raise an exception when the addition works?

What does the slash(/) in the parameter list of a function mean?

PEP 3118: New memoryview implementation and buffer protocol documentation

PEP 476: Enabling certificate verification by default for stdlib http clients

PEP 471 - os.scandir() function – a better and faster directory iterator

Why must ‘self’ be used explicitly in method definitions and calls?

argparse — Parser for command-line options, arguments and sub-commands

functools — Higher-order functions and operations on callable objects

multiprocessing.shared_memory —  Provides shared memory for direct access across processes

sysconfig — Provide access to Python’s configuration information

:class:`tweepy.asynchronous.asyncstream` --- asynchronous stream reference

TextClause.columns() will match columns positionally, not by name, when passed positionally

JSON Columns will not insert JSON NULL if no value is supplied and no default is established

Session.get_bind() handles a wider variety of inheritance scenarios

session.expunge() will fully detach an object that’s been deleted

ColumnProperty constructs work a lot better with aliases, order_by

Session.get_bind() will receive the Mapper in all relevant Query cases

query.update() now resolves string names into mapped attribute names

Python-side defaults invoked for each row individually when using a multivalued insert

Warnings emitted when comparing objects with None values to relationships

A “negated contains or equals” relationship comparison will use the current value of attributes, not the database value

API Change for new Bundle feature when custom row loaders are used

Many-to-one backref checks for collection duplicates during remove operation

Support for SQL Comments on Table, Column, includes DDL, reflection

INSERT FROM SELECT now includes Python and SQL-expression defaults

A UNION or similar of SELECTs with LIMIT/OFFSET/ORDER BY now parenthesizes the embedded selects

attributes.get_history() will query from the DB by default if value not present

Schema identifiers now carry along their own quoting information

Subquery Eager Loading will apply DISTINCT to the innermost SELECT for some queries

Large parameter and row values are now truncated in logging and exception displays

The typing system now handles the task of rendering “literal bind” values

TypeDecorator now works with Enum, Boolean, “schema” types automatically

Support for RANGE and ROWS specification within window functions

Stringify of Query will consult the Session for the correct dialect

New Function features, “WITHIN GROUP”, array_agg and set aggregate functions

Event listeners can not be added or removed from within that event’s runner

PyODBC driver name is required with hostname-based SQL Server connections

SQLite/Oracle have distinct methods for temporary table/view name reporting

The .autoincrement directive is no longer implicitly enabled for a composite primary key column

Subqueries no longer applied to uselist=False joined eager loads

New options allowing explicit persistence of NULL over a default

The match() operator now returns an agnostic MatchType compatible with MySQL’s floating point return value

MySQL SET Type Overhauled to support empty sets, unicode, blank value handling

Specific checks added for passing mapped classes, instances as SQL literals

Constraints referring to unattached Columns can auto-attach to the Table when their referred columns are attached

AssociationProxy stores class-specific state on a per-class basis

Joined eager loading where the same entity is present multiple times in one row

Changes regarding “unhashable” types, impacts deduping of ORM rows

ResultSet column matching enhancements; positional column setup for textual SQL

Correct SQL Types are Established from Indexed Access of ARRAY, JSON, HSTORE

The JSON cast() operation now requires .astext is called explicitly

String / varlength types no longer represent “max” explicitly on reflection

JSON “null” is inserted as expected with ORM operations, omitted when not present

Same-named backrefs will not raise an error when applied to concrete inheritance subclasses

“Friendly” stringification of Core SQL constructs without a dialect

Hybrid properties and methods now propagate the docstring as well as .info

Improvements to the Query.correlate method with polymorphic entities

Erroneous “new instance X conflicts with persistent instance Y” flush errors fixed

Improved Session state when a SAVEPOINT is cancelled by the database

Fix involving many-to-one object moves with user-initiated foreign key manipulations

Non-native boolean integer values coerced to zero/one/None in all cases

Use flag_dirty() to mark an object as “dirty” without any attribute changing

AssociationProxy any(), has(), contains() work with chained association proxies

Engines now invalidate connections, run error handlers for BaseException

passive_deletes=’all’ will leave FK unchanged for object removed from collection

Fixed issue involving single-table inheritance with select_from()

A @validates method receives all values on bulk-collection set before comparison

The IN / NOT IN operator’s empty collection behavior is now configurable; default expression simplified

Hybrid attributes support reuse among subclasses, redefinition of @getter

Pessimistic disconnection detection added to the connection pool

The after_rollback() Session event now emits before the expiration of objects

New “selectin” eager loading, loads all collections at once using IN

“selectin” polymorphic loading, loads subclasses using separate IN queries

Late-expanded IN parameter sets allow IN expressions with cached statements

Support for fields specification in INTERVAL, including full reflection

TypeEngine methods bind_expression, column_expression work with Variant, type-specific types

The typing behavior of custom operators has been made consistent

Parameter helper for multi-valued INSERT with contextual default generator

Horizontal Sharding extension supports bulk update and delete methods

Added basic reflection support for PostgreSQL partitioned tables

National char datatypes de-emphasized for generic unicode, re-enabled with option

FOR UPDATE clause is rendered within the joined eager load subquery as well as outside

AssociationProxy now provides standard column operators for a column-oriented target

Many-to-one replacement won’t raise for “raiseload” or detached for “old” object

New parameters to affect IDENTITY start and increment, use of Sequence deprecated

Query.join() handles ambiguity in deciding the “left” side more explicitly

cx_Oracle connect arguments modernized, deprecated parameters removed

Deprecation warnings are emitted for all deprecated elements; new deprecations added

Relationship to AliasedClass replaces the need for non primary mappers

Improved column labeling for simple column expressions using CAST or similar

Accessing an uninitialized collection attribute on a transient object no longer mutates __dict__

A SELECT statement is no longer implicitly considered to be a FROM clause

Transparent SQL Compilation Caching added to All DQL, DML Statements in Core, ORM

All IN expressions render parameters for each value in the list on the fly (e.g. expanding parameters)

Repaired internal importing conventions such that code linters may work correctly

The “New instance conflicts with existing identity” error is now a warning

RowProxy is no longer a “proxy”; is now called Row and behaves like an enhanced named tuple

Connection-level transactions can now be inactive based on subtransaction

Built-in FROM linting will warn for any potential cartesian products in a SELECT statement

SELECT objects and derived FROM clauses allow for duplicate columns and column labels

New “post compile” bound parameters used for LIMIT/OFFSET in Oracle, SQL Server

Removed “join rewriting” logic from SQLite dialect; updated imports

Persistence-related cascade operations disallowed with viewonly=True

Python Dataclasses, attrs Supported w/ Declarative, Imperative Mappings

Stricter behavior when querying inheritance mappings using custom queries

ORM Query is internally unified with select, update, delete; 2.0 style execution available

ORM Batch inserts with psycopg2 now batch statements with RETURNING in most cases

Enum and Boolean datatypes no longer default to “create constraint”

psycopg2 dialect features “execute_values” with RETURNING for INSERT statements by default

Python 3.6 is the minimum Python 3 version; Python 2.7 still supported

psycopg2 dialect no longer has limitations regarding bound parameter names

Many Core and ORM statement objects now perform much of their construction and validation in the compile phase

No more generation of an implicit KEY for composite primary key w/ AUTO_INCREMENT

ORM Bulk Update and Delete use RETURNING for “fetch” strategy when available

select().join() and outerjoin() add JOIN criteria to the current query, rather than creating a subquery

Routing Explicit Joins/Statements into Eagerly Loaded Collections

Fine grained control over cx_Oracle data binding performance with setinputsizes

Disabling or using an alternate dictionary to cache some (or all) statements

Using Lambdas to add significant speed gains to statement production

QueuePool limit of size <x> overflow <y> reached, connection timed out, timeout <z>

This Session’s transaction has been rolled back due to a previous exception during flush

Expected FROM clause, got Select.  To create a FROM clause, use the .subquery() method

This connection is on an inactive transaction.  Please rollback() fully before proceeding

The <some function> in SQLAlchemy 2.0 will no longer <something>

For relationship <relationship>, delete-orphan cascade is normally configured only on the “one” side of a one-to-many relationship, and not on the “many” side of a many-to-one or many-to-many relationship.

Instance <instance> is already associated with an instance of <instance> via its <attribute> attribute, and is only allowed a single parent.

Parent instance <x> is not bound to a Session; (lazy load/deferred load/refresh/etc.) operation cannot proceed

select() construct created in “legacy” mode; keyword arguments, etc.

A bind was located via legacy bound metadata, but since future=True is set on this Session, this bind is ignored.

A value is required for bind parameter <x> (in parameter group <y>)

Compiler StrSQLCompiler can’t render element of type <element type>

relationship X will copy column Q to column P, which conflicts with relationship(s): ‘Y’

I’m getting a warning or error about “Implicitly combining column X under attribute Y”

Using DBAPI Autocommit Allows for a Readonly Version of Transparent Reconnect

Why does post_update emit UPDATE in addition to the first UPDATE?

My Query does not return the same number of objects as query.count() tells me - why?

I’m re-loading data with my Session but it isn’t seeing changes that I committed elsewhere

“This Session’s transaction has been rolled back due to a previous exception during flush.” (or similar)

I’m using op() to generate a custom operator and my parenthesis are not coming out correctly

Why are percent signs being doubled up when stringifying SQL statements?

How do I render SQL expressions as strings, possibly with bound parameters inlined?

Why is ORDER BY required with LIMIT (especially with subqueryload())?

Floating Point String-Conversion Precision Configurable for Native Floating Point Types

Select/Query LIMIT / OFFSET may be specified as an arbitrary SQL expression

Improvements to declarative mixins, @declared_attr and related features

The use_alter flag on ForeignKeyConstraint is (usually) no longer needed

Many JOIN and LEFT OUTER JOIN expressions will no longer be wrapped in (SELECT * FROM ..) AS ANON_1

Identity Columns (GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY)

Dealing with Key Mutations and back-populating for Dictionary collections

The consideration of a “pending” object as an “orphan” has been made more aggressive

create_all() and drop_all() will now honor an empty list as such

Label constructs can now render as their name alone in an ORDER BY

Columns can reliably get their type from a column referred to via ForeignKey

select() no longer accepts varied constructor arguments, columns are passed positionally

Library-level (but not driver level) “Autocommit” removed from both Core and ORM

“Implicit” and “Connectionless” execution, “bound metadata” removed

ORM Query  - Joining / loading on relationships uses attributes, not strings

Using DISTINCT with additional columns, but only select the entity

Selecting from the query itself as a subquery, e.g. “from_self()”

_query.Query.select_from() no longer applies the clause to corresponding entities

Improved rendering of Boolean constants, NULL constants, conjunctions

Composite attributes are now returned as their object form when queried on a per-attribute basis

viewonly=True on relationship() prevents history from taking effect

A bindparam() construct with no type gets upgraded via copy when a type is available

The “password” portion of a create_engine() no longer considers the + sign as an encoded space

PostgreSQL CREATE TYPE <x> AS ENUM now applies quoting to values

Right inner join nesting now the default for joinedload with innerjoin=True

Priority of attribute changes on relationship-bound attributes vs. FK-bound may appear to change

Changes to attribute events and other operations regarding attributes that have no pre-existing value

Change to single-table-inheritance criteria when using from_self(), count()

single-table-inheritance criteria added to all ON clauses unconditionally

Joined/Subquery eager loading explicitly disallowed with yield_per

“Commands out of sync; you can’t run this command now” / “This result object does not return rows. It has been closed automatically”

Rendering ON UPDATE CURRENT TIMESTAMP for MySQL / MariaDB’s explicit_defaults_for_timestamp

I’m getting errors related to “numpy.int64”, “numpy.bool_”, etc.

Selecting ORM Objects Inline with UPDATE.. RETURNING or INSERT..RETURNING

Creating an Explicit Base Non-Dynamically (for use with mypy, similar)

Table values, Table and Column valued functions, Row and Tuple objects

Notes on Delete - Deleting Objects Referenced from Collections and Scalar Relationships

Joining a Session into an External Transaction (such as for test suites)

When do I construct a Session, when do I commit it, and when do I close it?

Partitioning Strategies (e.g. multiple database backends per Session)

Using More Specific Text with table(), _expression.literal_column(), and _expression.column()

Marking Implicitly Generated Values, timestamps, and Triggered Columns

Column Valued Functions - Table Valued Function as a Scalar Column