Skip to content

Commit

Permalink
Update readme and change a few class names.
Browse files Browse the repository at this point in the history
  • Loading branch information
JMSchietekat committed Aug 11, 2021
1 parent 467a686 commit 305f2a8
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 59 deletions.
25 changes: 24 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
# Local Environment Variables

This package allows you to specify which environmental variable you require in you application. It will create a `.env` file, prompt you to populate and add the `.env` file to your `.gitignore` file.
This package allows you to specify which environmental variable you require in your application. It will create a `.env` file, prompt you to populate it, and add the `.env` file to your `.gitignore` file.

The functionality described is in line with the guidelines set out in the [The Twelve-Factor App](https://12factor.net/) section [III Config](https://12factor.net/config).

## Implementation

```python
from local_env_vars.env import LocalEnvVars

env = EnvironmentManager("sql_server_address", "sql_username", "sql_password")

connection_string = "Driver={{SQL Server}};Server={0}; Database=AdventureWorks;uid={1};pwd={2}".format(
env.vars['sql_server_address'], env.vars['sql_username'], env.vars['sql_password']
)
```

Running this code for the first time will create a `.env` file with the following content. It will throw an exception reporting that you must provide values to the keys.

`{"sql_server_address": "", "sql_username": "", "sql_password": ""}`

After you have populated the keys with values you will be able to execute the code without any exceptions.



30 changes: 15 additions & 15 deletions src/local_env_vars/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
import json


class EnvironmentManager():
class LocalEnvVars():

def __init__(self, *argv):
assert len(argv) > 0, "Supply at least 1 argument."

self._env_file = '.env'
self._ignore_file = '.gitignore'

if(not EnvironmentManager.file_exists(self._ignore_file)):
if(not LocalEnvVars.file_exists(self._ignore_file)):
with open(self._ignore_file, "w") as filewriter:
filewriter.write(self._env_file)
else:
Expand All @@ -24,28 +24,28 @@ def __init__(self, *argv):
filewriter.write('\n' + self._env_file)

# Create env file if it does not exist.
if(not EnvironmentManager.file_exists(self._env_file)):
if(not LocalEnvVars.file_exists(self._env_file)):
self.create_file(self._env_file)
EnvironmentManager.dictionary_to_json_file(
LocalEnvVars.dictionary_to_json_file(
self._env_file, self.args_to_empty_dictionary(*argv))
raise EnvironmentException(
raise LocalEnvVarsException(
"New .env file created with keys. Add their values and try again.")

self.dictionary = EnvironmentManager.json_file_to_dictionary(
self.vars = LocalEnvVars.json_file_to_dictionary(
self._env_file)

# Check that application and env file's keys match, otherwise update env file.
if(not EnvironmentManager.dict_has_equal_keys(EnvironmentManager.args_to_empty_dictionary(*argv), self.dictionary)):
self.dictionary = EnvironmentManager.merge_dictionary_with_keys(
self.dictionary, *argv)
EnvironmentManager.dictionary_to_json_file(
self._env_file, self.dictionary)
raise EnvironmentException(
if(not LocalEnvVars.dict_has_equal_keys(LocalEnvVars.args_to_empty_dictionary(*argv), self.vars)):
self.vars = LocalEnvVars.merge_dictionary_with_keys(
self.vars, *argv)
LocalEnvVars.dictionary_to_json_file(
self._env_file, self.vars)
raise LocalEnvVarsException(
"Environment keys differ. Keys will be added/removed. Add the values and try again.")

# Check that all variables are populated.
if(not EnvironmentManager.dict_has_values(self.dictionary)):
raise EnvironmentException(
if(not LocalEnvVars.dict_has_values(self.vars)):
raise LocalEnvVarsException(
"Environment keys are set up. Some values are missing, please add them and try again.")

@staticmethod
Expand Down Expand Up @@ -107,7 +107,7 @@ def merge_dictionary_with_keys(dict1={}, *argv):
return dictionary


class EnvironmentException(Exception):
class LocalEnvVarsException(Exception):
"""
Exception raised for an environment setup issue.
"""
Expand Down
86 changes: 43 additions & 43 deletions tests/test_local_env_vars.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import os
import json

from src.local_env_vars.env import EnvironmentManager, EnvironmentException
from src.local_env_vars.env import LocalEnvVars, LocalEnvVarsException


class TestIntegration(unittest.TestCase):
Expand All @@ -27,19 +27,19 @@ def test_create_ignore_file_if_it_does_not_exist(self):
except Exception:
pass

EnvironmentManager.dictionary_to_json_file(
LocalEnvVars.dictionary_to_json_file(
".env", {"sql_username": "un", "sql_password": "pwd"})
self.envManager = EnvironmentManager("sql_username", "sql_password")
self.envManager = LocalEnvVars("sql_username", "sql_password")

self.assertTrue(os.path.exists(".gitignore"))

def test_append_to_empty_ignore_file_when_env_not_ignored(self):
with open(".gitignore", 'a'):
os.utime(".gitignore", None)

EnvironmentManager.dictionary_to_json_file(
LocalEnvVars.dictionary_to_json_file(
".env", {"sql_username": "un", "sql_password": "pwd"})
self.envManager = EnvironmentManager("sql_username", "sql_password")
self.envManager = LocalEnvVars("sql_username", "sql_password")

found = False

Expand All @@ -53,9 +53,9 @@ def test_append_to_non_empty_ignore_file_when_env_not_ignored(self):
with open(".gitignore", 'w') as filewriter:
filewriter.write('*bak')

EnvironmentManager.dictionary_to_json_file(
LocalEnvVars.dictionary_to_json_file(
".env", {"sql_username": "un", "sql_password": "pwd"})
self.envManager = EnvironmentManager("sql_username", "sql_password")
self.envManager = LocalEnvVars("sql_username", "sql_password")

found = 0

Expand All @@ -69,9 +69,9 @@ def test_append_to_non_empty_ignore_file_when_env_already_ignored(self):
with open(".gitignore", 'w') as filewriter:
filewriter.write('.env')

EnvironmentManager.dictionary_to_json_file(
LocalEnvVars.dictionary_to_json_file(
".env", {"sql_username": "un", "sql_password": "pwd"})
self.envManager = EnvironmentManager("sql_username", "sql_password")
self.envManager = LocalEnvVars("sql_username", "sql_password")

found = 0

Expand All @@ -87,52 +87,52 @@ def test_create_env_file_with_no_prior(self):
except FileNotFoundError:
pass

self.assertRaises(EnvironmentException, lambda: EnvironmentManager(
self.assertRaises(LocalEnvVarsException, lambda: LocalEnvVars(
"sql_server_address", "sql_username", "sql_password"))

dictionary = EnvironmentManager.json_file_to_dictionary(".env")
dictionary = LocalEnvVars.json_file_to_dictionary(".env")

self.assertDictEqual(
dictionary, {"sql_server_address": "", "sql_username": "", "sql_password": ""})

def test_persist_env_file_when_exact_keys_are_used(self):
EnvironmentManager.dictionary_to_json_file(
LocalEnvVars.dictionary_to_json_file(
".env", {
"username": "my_username",
"password": "my_password"
}
)
self.envManager = EnvironmentManager("username", "password")
self.lev = LocalEnvVars("username", "password")

self.assertDictEqual(self.envManager.dictionary, {
self.assertDictEqual(self.lev.vars, {
"username": "my_username",
"password": "my_password"
}
)

def test_exception_is_thrown_with_unpopulated_values(self):
EnvironmentManager.dictionary_to_json_file(
LocalEnvVars.dictionary_to_json_file(
".env",
{
"username": "my_username",
"password": ""
}
)

self.assertRaises(EnvironmentException, lambda: EnvironmentManager(
self.assertRaises(LocalEnvVarsException, lambda: LocalEnvVars(
"username", "password"))

def test_added_keys_on_init_to_be_added_to_env_file(self):
EnvironmentManager.dictionary_to_json_file(
LocalEnvVars.dictionary_to_json_file(
".env",
{
"username": "my_username",
"password": "my_password"
}
)

self.assertRaises(EnvironmentException,
lambda: EnvironmentManager(
self.assertRaises(LocalEnvVarsException,
lambda: LocalEnvVars(
"username", "password", "ssh_key")
)

Expand All @@ -144,16 +144,16 @@ def test_added_keys_on_init_to_be_added_to_env_file(self):
readline, '{"username": "my_username", "password": "my_password", "ssh_key": ""}')

def test_removed_keys_on_init_to_be_removed_from_env_file(self):
EnvironmentManager.dictionary_to_json_file(
LocalEnvVars.dictionary_to_json_file(
".env",
{
"username": "my_username",
"password": "my_password"
}
)

self.assertRaises(EnvironmentException,
lambda: EnvironmentManager("username"))
self.assertRaises(LocalEnvVarsException,
lambda: LocalEnvVars("username"))

readline = ""

Expand All @@ -163,7 +163,7 @@ def test_removed_keys_on_init_to_be_removed_from_env_file(self):
self.assertEqual(readline, '{"username": "my_username"}')

def test_empty_initialisation_to_throw_assertion_error(self):
self.assertRaises(AssertionError, lambda: EnvironmentManager())
self.assertRaises(AssertionError, lambda: LocalEnvVars())

class TestStaticArgsToEmptyDictionary(unittest.TestCase):
"""
Expand All @@ -172,7 +172,7 @@ class TestStaticArgsToEmptyDictionary(unittest.TestCase):

def test_input_args_and_compare_with_expected_dictionary(self):

dictionary = EnvironmentManager.args_to_empty_dictionary(
dictionary = LocalEnvVars.args_to_empty_dictionary(
"args", "to", "test")

self.assertDictEqual(dictionary, {"args": "", "to": "", "test": ""})
Expand All @@ -194,9 +194,9 @@ def tearDown(self):
os.remove(self.filename)

def test_create_file_when_it_already_existed(self):
EnvironmentManager.create_file(self.filename)
LocalEnvVars.create_file(self.filename)
self.assertRaises(
AssertionError, lambda: EnvironmentManager.create_file(self.filename))
AssertionError, lambda: LocalEnvVars.create_file(self.filename))


class TestStaticDictHasEqualKeys(unittest.TestCase):
Expand All @@ -208,32 +208,32 @@ def test_dictionaries_with_non_equal_keys_to_be_false(self):
dict1 = {"args": "", "to": "", "test": ""}
dict2 = {"args": "value1", "to": "value2", "tes": "value3"}

self.assertFalse(EnvironmentManager.dict_has_equal_keys(dict1, dict2))
self.assertFalse(LocalEnvVars.dict_has_equal_keys(dict1, dict2))

def test_dictionaries_with_a_subset_of_equal_keys_to_be_false(self):
dict1 = {"args": "", "to": "", "test": ""}
dict2 = {"args": "value1", "to": "value2",
"test": "value3", "with": ""}

self.assertFalse(EnvironmentManager.dict_has_equal_keys(dict1, dict2))
self.assertFalse(LocalEnvVars.dict_has_equal_keys(dict1, dict2))

def test_dictionaries_with_equal_keys_to_be_true(self):
dict1 = {"args": "", "to": "", "test": ""}
dict2 = {"args": "value1", "to": "value2", "test": "value3"}

self.assertTrue(EnvironmentManager.dict_has_equal_keys(dict1, dict2))
self.assertTrue(LocalEnvVars.dict_has_equal_keys(dict1, dict2))

def test_dictionaries_with_equal_keys_in_different_order_to_be_true(self):
dict1 = {"args": "", "to": "", "test": ""}
dict2 = {"to": "value2", "args": "value1", "test": "value3"}

self.assertTrue(EnvironmentManager.dict_has_equal_keys(dict1, dict2))
self.assertTrue(LocalEnvVars.dict_has_equal_keys(dict1, dict2))

def test_empty_dictionary(self):
dict1 = {}
dict2 = {}

self.assertTrue(EnvironmentManager.dict_has_equal_keys(dict1, dict2))
self.assertTrue(LocalEnvVars.dict_has_equal_keys(dict1, dict2))


class TestStaticDictHasValues(unittest.TestCase):
Expand All @@ -243,16 +243,16 @@ class TestStaticDictHasValues(unittest.TestCase):

def test_with_values_to_be_true(self):
dictionary = {"args": "1", "to": "2", "test": "3"}
self.assertTrue(EnvironmentManager.dict_has_values(dictionary))
self.assertTrue(LocalEnvVars.dict_has_values(dictionary))

def test_with_omitted_values_to_be_false(self):
dictionary = {"args": "1", "to": "2", "test": ""}
self.assertFalse(EnvironmentManager.dict_has_values(dictionary))
self.assertFalse(LocalEnvVars.dict_has_values(dictionary))

def test_with_zero_items_should_throw_error(self):
dictionary = {}
self.assertRaises(
AssertionError, lambda: EnvironmentManager.dict_has_values(dictionary))
AssertionError, lambda: LocalEnvVars.dict_has_values(dictionary))


class TestStaticDictionaryToJsonFile(unittest.TestCase):
Expand All @@ -265,7 +265,7 @@ def test_provided_dictionary_is_writen_to_file(self):
filename = ".env"
readline = ""

EnvironmentManager.dictionary_to_json_file(filename, dictionary)
LocalEnvVars.dictionary_to_json_file(filename, dictionary)

with open(filename, "r") as filereader:
readline = filereader.read()
Expand All @@ -287,12 +287,12 @@ def test_when_file_exists(self):
filewriter = open(self.filename, "w+")
filewriter.close()

self.assertTrue(EnvironmentManager.file_exists(self.filename))
self.assertTrue(LocalEnvVars.file_exists(self.filename))

os.remove(self.filename)

def test_when_file_does_not_exists(self):
self.assertFalse(EnvironmentManager.file_exists(self.filename))
self.assertFalse(LocalEnvVars.file_exists(self.filename))


class TestStaticJsonFileToDictionary(unittest.TestCase):
Expand All @@ -310,15 +310,15 @@ def test_with_valid_json(self):
with open(self.filename, 'w') as filewriter:
json.dump({"one": "1", "two": "22", "three": ""}, filewriter)

self.assertDictEqual(EnvironmentManager.json_file_to_dictionary(
self.assertDictEqual(LocalEnvVars.json_file_to_dictionary(
self.filename), {"one": "1", "two": "22", "three": ""})

def test_with_invalid_json(self):
with open(self.filename, 'w') as filewriter:
filewriter.write('{"one":"1","two":"22", "three":""')

self.assertRaises(
Exception, lambda: EnvironmentManager.json_file_to_dictionary(self.filename))
Exception, lambda: LocalEnvVars.json_file_to_dictionary(self.filename))


class TestStaticMergeDictionaryWithKeys(unittest.TestCase):
Expand All @@ -330,29 +330,29 @@ def test_new_key_added(self):
keys = ["one", "two", "three"]
key_vals = {"one": "1", "two": "22"}

output = EnvironmentManager.merge_dictionary_with_keys(key_vals, *keys)
output = LocalEnvVars.merge_dictionary_with_keys(key_vals, *keys)

self.assertDictEqual(output, {"one": "1", "two": "22", "three": ""})

def test_key_removed(self):
keys = ["one"]
key_vals = {"one": "1", "two": "22"}

output = EnvironmentManager.merge_dictionary_with_keys(key_vals, *keys)
output = LocalEnvVars.merge_dictionary_with_keys(key_vals, *keys)

self.assertDictEqual(output, {"one": "1"})

def test_new_key_added_and_then_removed(self):
keys = ["one", "two", "three"]
key_vals = {"one": "1", "two": "22"}

output = EnvironmentManager.merge_dictionary_with_keys(key_vals, *keys)
output = LocalEnvVars.merge_dictionary_with_keys(key_vals, *keys)

self.assertDictEqual(output, {"one": "1", "two": "22", "three": ""})

keys2 = ["one", "three"]

output = EnvironmentManager.merge_dictionary_with_keys(output, *keys2)
output = LocalEnvVars.merge_dictionary_with_keys(output, *keys2)

self.assertDictEqual(output, {"one": "1", "three": ""})

Expand Down

0 comments on commit 305f2a8

Please sign in to comment.