- Install cookiecutter
- Install poetry
PS C:\Users\testuser\projects> cookiecutter https://github.com/s-raza/cookiecutter-poetry-vscode --directory standard
project_name [pythonproject]:
pyversion [3.9]:
authors [[]]:
black_target_versions [["py39"]]:
Installing poetry virtual env ...done
Poetry virtual env installed at: C:\Users\testuser\AppData\Local\pypoetry\Cache\virtualenvs\pythonproject-B9yC7h6M-py3.9
Initializing GIT repo ...done
Installing pre-commit ...done
Auto Updating pre-commit ...done
Adding project files to GIT repo ...done
Committing to GIT repo ...done
Updating vscode config with virtual env path ...done
- Intializes Python virtual environment using Poetry. Poetry should be installed and configured before running cookiecutter.
- Installs development modules within the Poetry virtual environment with basic configurations for - pytest, pytest-cov, ptpython, pre-commit, flake8, black, mypy and isort.
- Initializes a local Github repository for the files and folders rendered by cookiecutter.
- Installs pre-commit hooks in GIT for pre-commit, flake8, black, mypy and isort
- Autoupdates all the defined hooks in GIT for pre-commit
- Renders a basic vscode settings.json file with a dark theme.
- Updates the vscode pythonPath setting with the virtual environment python path created using Poetry.
- Performs an initial GIT commit of the rendered cookiecutter project, with pre-defined files to ignore in .gitignore.
Settings for your Python program can be defined in two locations - .json files in the config directory and its sub directories or the .env file. The config directory is rendered by cookiecutter in the main project directory by default.
Once the settings are defined in either of these locations, they can be accessed by importing the config.py module anywhere in your code.
The values of the configuration keys with the same name accross all the setting sources (config directory and .env) are collected under a common key name.
Example Usage
Settings from pythonproject/config/config.json
{
"env_config_key": "default_",
"emailer": {
"send": true
}
}
Settings from pythonproject/config/emailer/email_config.json
{
"emailer": {
"subject": "Subject",
"body": "Body"
}
}
Settings from .env
default_emailer = {"username": "Username", "password": "Password", "api_key": {"secret": "Secret", "key": "KEY"}}
Using the config settings defined above in your program
C:\Users\testuser\projects\pythonproject>ptpython
>>> import pythonproject.config as cfg
>>> import pprint as pp
>>> pp.pp(cfg.emailer)
{'send': True,
'subject': 'Subject',
'body': 'Body',
'username': 'Username',
'password': 'Password',
'api_key': {'secret': 'Secret', 'key': 'KEY'}}
>>> cfg.emailer["api_key"]["secret"]
'Secret'
>>> cfg.emailer["api_key"]["key"]
'KEY'
>>> cfg.emailer['send'] is False
False
Settings from json config file
Files with .json extension in the config directory can be organized into sub directories having one or more .json files. As long as the file extension is .json and the contents of it follow standard json formatting, the settings will be accessible in your Python progam.
Each key from all the .json files found in the config folder and its sub-folders is added to the global namespace of the config.py module.
Sensitive settings from .env files
This is to be used to populate sensitive settings like passwords and API keys. The .env file is excluded by default from the GIT repository created during intialization of the cookiecutter project.
Settings in the .env file can be defined just like environment variables. However a prefix string should be attached to each setting entry, which should be defined in one of the .json files in the config directory with the env_config_key. A default env_config_key with the value default_ is already defined in the config/config.json file that is rendered by cookiecutter. Settings that do not have this prefix in the .env file are ignored.
Database settings
-
Connecting to a database server
If a key "active_database" is defined in either config/config.json or .env files (default key prefix is applied to settings from .env as explained above) the database key corresponding to the database settings is populated into a 'database' variable in the global namespace of config.py. If an "active_database" key is not defined, the 'database' variable will be initialized to None.
Example using .env:
default_test_db = {"dialect": "mysql+mysqldb","user": "dbuser","password": "dbuserpass","host": "localhost","db_name": "dbname","db_port": null,"db_options": {"charset": "utf8mb4"},"sqlalchemy_options": {"pool_recycle": 3600}} default_active_database = "test_db"We have a setting
default_active_databasein the .env file which will be available asactive_databasein the global namespace of config.py. The value of theactive_databasevariable will be "test_db"
There is also a settingdefault_test_dbwhich will be available astest_dbin the global name space of config.py. The value of thetest_dbvariable will be the dictionary with the database settings assigned to thedefault_test_dbin the .env file.
Effectively adatabasevariable will be initialized in the global namespace of config.py, with the settings dictionary assigned todefault_test_dbin the .env file.
Addtionally aconn_stringkey will be constructed and added to thedatabasevariable.
Demo:PS C:\Users\testuser> cd .\projects\pythonproject\ PS C:\Users\testuser\projects\pythonproject> poetry shell Spawning shell within C:\Users\testuser\AppData\Local\pypoetry\Cache\virtualenvs\pythonproject-B9yC7h6M-py3.9 Microsoft Windows [Version 10.0.19042.1083] (c) Microsoft Corporation. All rights reserved. C:\Users\testuser\projects\pythonproject>ptpython >>> import pythonproject.config as cfg >>> import pprint as pp >>> pp.pp(cfg.database, indent=4) { 'dialect': 'mysql+mysqldb', 'user': 'dbuser', 'password': 'dbuserpass', 'host': 'localhost', 'db_name': 'dbname', 'db_port': None, 'db_options': {'charset': 'utf8mb4'}, 'sqlalchemy_options': {'pool_recycle': 3600}, 'conn_string': 'mysql+mysqldb://dbuser:dbuserpass@localhost/dbname?charset=utf8mb4&'} >>> cfg.database['conn_string'] 'mysql+mysqldb://dbuser:dbuserpass@localhost/dbname?charset=utf8mb4&' >>> cfg.active_database 'test_db' >>> pp.pp(cfg.test_db, indent=4) { 'dialect': 'mysql+mysqldb', 'user': 'dbuser', 'password': 'dbuserpass', 'host': 'localhost', 'db_name': 'dbname', 'db_port': None, 'db_options': {'charset': 'utf8mb4'}, 'sqlalchemy_options': {'pool_recycle': 3600}, 'conn_string': 'mysql+mysqldb://dbuser:dbuserpass@localhost/dbname?charset=utf8mb4&'} -
Connecting to SQLITE
If the activated database setting has a 'sqlite' key, it's value is assigned as the file name for the SQLITE file in the connection string for it.
Cotents of
pythonproject/config/config.json{ "env_config_key": "default_", "test_db": {"sqlite": "sqlite_file.db"} }Cotents of
pythonproject/.envdefault_project_name = pythonproject default_test_db = {"dialect": "mysql+mysqldb","user": "dbuser","password": "dbuserpass","host": "localhost","db_name": "dbname","db_port": null,"db_options": {"charset": "utf8mb4"},"sqlalchemy_options": {"pool_recycle": 3600}} default_active_database = "test_db"Usage
C:\Users\testuser\projects\pythonproject>ptpython >>> import pythonproject.config as cfg >>> import pprint as pp >>> pp.pp(cfg.database, indent=4) { 'sqlite': 'sqlite_file.db', 'dialect': 'mysql+mysqldb', 'user': 'dbuser', 'password': 'dbuserpass', 'host': 'localhost', 'db_name': 'dbname', 'db_port': None, 'db_options': {'charset': 'utf8mb4'}, 'sqlalchemy_options': {'pool_recycle': 3600}, 'conn_string': 'sqlite:///sqlite_file.db'} >>> cfg.database["conn_string"] 'sqlite:///sqlite_file.db'