From acb07f79e4526a67225c027a3b7a9c099dcd1b49 Mon Sep 17 00:00:00 2001
From: jonathanlutterbeck
<48634262+jonathanlutterbeck@users.noreply.github.com>
Date: Fri, 15 Apr 2022 15:34:24 +0200
Subject: [PATCH 01/11] created configloader.py
added a configuration loader which checks for existing config files.
If the folder is not found it is created.
If the file is not found the default empty config file is copied to users home directory.
---
.idea/.gitignore | 3 +
.idea/gridscale_api_client_python.iml | 15 ++++
.idea/inspectionProfiles/Project_Default.xml | 20 +++++
.../inspectionProfiles/profiles_settings.xml | 6 ++
.idea/misc.xml | 4 +
.idea/modules.xml | 8 ++
.idea/vcs.xml | 6 ++
examples/config.yaml | 9 +++
examples/configloader.py | 80 +++++++++++++++++++
examples/examples.py | 15 ++--
10 files changed, 160 insertions(+), 6 deletions(-)
create mode 100644 .idea/.gitignore
create mode 100644 .idea/gridscale_api_client_python.iml
create mode 100644 .idea/inspectionProfiles/Project_Default.xml
create mode 100644 .idea/inspectionProfiles/profiles_settings.xml
create mode 100644 .idea/misc.xml
create mode 100644 .idea/modules.xml
create mode 100644 .idea/vcs.xml
create mode 100644 examples/config.yaml
create mode 100644 examples/configloader.py
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/gridscale_api_client_python.iml b/.idea/gridscale_api_client_python.iml
new file mode 100644
index 0000000..14273e4
--- /dev/null
+++ b/.idea/gridscale_api_client_python.iml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..bc85450
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..5706053
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..52045b0
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/config.yaml b/examples/config.yaml
new file mode 100644
index 0000000..9f7be7d
--- /dev/null
+++ b/examples/config.yaml
@@ -0,0 +1,9 @@
+projects:
+- name: default
+ userId: user123
+ token: pass123
+ url: https://api.gridscale.io
+- name: something-else
+ userId: user456
+ token: pass456
+ url: https://api.gridscale.io
\ No newline at end of file
diff --git a/examples/configloader.py b/examples/configloader.py
new file mode 100644
index 0000000..f8323d3
--- /dev/null
+++ b/examples/configloader.py
@@ -0,0 +1,80 @@
+import shutil
+import yaml
+import sys
+import os.path
+
+#TODO: change active project
+project = "somthing-else"
+
+def which_path():
+ #check if os is linux
+ if(sys.platform == "linux" or sys.platform == "linux2"):
+ path = "~/.config/gridscale"
+ path = os.path.expanduser(path)
+ if not os.path.exists(path):
+ os.makedirs(path)
+ #check if os is windows
+ elif(sys.platform == "win32" or sys.platform == "cygwin" or sys.platform == "msys"):
+ path = "%APPDATA%\gridscale"
+ path = os.path.expanduser(path)
+ if not os.path.exists(path):
+ os.makedirs(path)
+ #check if os is mac os
+ elif(sys.platform == "darwin" or sys.platform == "os2" or sys.platform == "os2emx"):
+ path = "~/Library/Application Support/gridscale"
+ path = os.path.expanduser(path)
+ if not os.path.exists(path):
+ os.makedirs(path)
+ else:
+ "Operating System not supported"
+
+ return path
+
+def create_config(path):
+ cwd = os.getcwd()
+ shutil.copyfile(f"{cwd}/config.yaml", path)
+ print(f"New config file created, edit config file at: {path}")
+ return
+
+def load_config(projectname, goal, path):
+ with open(f"{path}", 'r') as stream:
+ try:
+ data = yaml.safe_load(stream)
+
+ for value in data.values():
+ for x in range(len(value)):
+ result = value[x]
+ #returns userID and token for the selected project
+ if (result.get("name") == projectname):
+ userid = result.get("userId")
+ token = result.get("token")
+ except yaml.YAMLError as exc:
+ print(exc)
+
+ if(goal == "id"):
+ return userid
+ elif(goal == "token"):
+ return token
+
+def load_token(project):
+ syspath = which_path() + "/config.yaml"
+ goal = "token"
+
+ # check if config file exists
+ if not os.path.exists(syspath):
+ create_config(syspath)
+ return load_config(project, goal, syspath)
+ else:
+ return load_config(project, goal, syspath)
+
+
+def load_userid(project):
+ syspath = which_path() + "/config.yaml"
+ goal = "id"
+
+ # check if config file exists
+ if not os.path.exists(syspath):
+ create_config(syspath)
+ return load_config(project, goal, syspath)
+ else:
+ return load_config(project, goal, syspath)
diff --git a/examples/examples.py b/examples/examples.py
index 2136e38..ee20fa8 100644
--- a/examples/examples.py
+++ b/examples/examples.py
@@ -7,6 +7,8 @@
from gs_api_client import SyncGridscaleApiClient, GridscaleApiClient, models
from gs_api_client import Configuration
+from configloader import load_token, load_userid
+
if __name__ == '__main__':
@@ -16,11 +18,12 @@
# api_config.debug = True
api_config.host = 'https://api.gridscale.io'
- #TODO: Insert your API token and User ID
- api_config.api_key['X-Auth-Token'] = "AUTH_TOKEN"
- api_config.api_key['X-Auth-UserId'] = "USER_UUID"
- # api_config.debug = True
-
+ #TODO: Change project
+ project = "default"
+ api_config.api_key['X-Auth-Token'] = load_token(project)
+ api_config.api_key['X-Auth-UserId'] = load_userid(project)
+ api_config.debug = True
+
print('-' * 80)
client = SyncGridscaleApiClient(configuration=api_config, http_info=False)
@@ -34,7 +37,7 @@
get_templates_response = client.get_templates()
templates = get_templates_response['templates'].values()
template_by_name = index_by_key(templates, 'name')
- template = template_by_name['Debian 9']
+ template = template_by_name['Debian 11']
# create storage
create_storage_response = client.create_storage({
From 09ef4af0001ce24eabaf44f0dc47de10df9622f5 Mon Sep 17 00:00:00 2001
From: jonathanlutterbeck
<48634262+jonathanlutterbeck@users.noreply.github.com>
Date: Fri, 15 Apr 2022 20:34:34 +0200
Subject: [PATCH 02/11] improved code
added suggestions from pylint
---
examples/configloader.py | 9 ++++-----
examples/examples.py | 2 +-
2 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/examples/configloader.py b/examples/configloader.py
index f8323d3..75bccce 100644
--- a/examples/configloader.py
+++ b/examples/configloader.py
@@ -1,26 +1,26 @@
import shutil
-import yaml
import sys
import os.path
+import yaml
#TODO: change active project
project = "somthing-else"
def which_path():
#check if os is linux
- if(sys.platform == "linux" or sys.platform == "linux2"):
+ if(sys.platform in ("linux", "linux2")):
path = "~/.config/gridscale"
path = os.path.expanduser(path)
if not os.path.exists(path):
os.makedirs(path)
#check if os is windows
- elif(sys.platform == "win32" or sys.platform == "cygwin" or sys.platform == "msys"):
+ elif(sys.platform in ("win32", "cygwin", "msys")):
path = "%APPDATA%\gridscale"
path = os.path.expanduser(path)
if not os.path.exists(path):
os.makedirs(path)
#check if os is mac os
- elif(sys.platform == "darwin" or sys.platform == "os2" or sys.platform == "os2emx"):
+ elif(sys.platform in ("darwin", "os2", "os2emx")):
path = "~/Library/Application Support/gridscale"
path = os.path.expanduser(path)
if not os.path.exists(path):
@@ -34,7 +34,6 @@ def create_config(path):
cwd = os.getcwd()
shutil.copyfile(f"{cwd}/config.yaml", path)
print(f"New config file created, edit config file at: {path}")
- return
def load_config(projectname, goal, path):
with open(f"{path}", 'r') as stream:
diff --git a/examples/examples.py b/examples/examples.py
index ee20fa8..9a1a572 100644
--- a/examples/examples.py
+++ b/examples/examples.py
@@ -3,11 +3,11 @@
from pprint import pprint
from uuid import uuid4
from index_by.key import index_by_key
+from configloader import load_token, load_userid
from gs_api_client import SyncGridscaleApiClient, GridscaleApiClient, models
from gs_api_client import Configuration
-from configloader import load_token, load_userid
if __name__ == '__main__':
From 2c620621beae4eaa65a77500c68198e17bda6b53 Mon Sep 17 00:00:00 2001
From: Benjamin Kircher
Date: Fri, 22 Apr 2022 11:12:10 +0200
Subject: [PATCH 03/11] Add test case for load_config
Add a test case that loads a simple YAML file with two projects. You can
run tests by executing `pytest` in the project root. Note that the test
currently fails.
---
examples/__init__.py | 0
tests/example-config.yaml | 10 ++++++++++
tests/test_config.py | 16 ++++++++++++++++
3 files changed, 26 insertions(+)
create mode 100644 examples/__init__.py
create mode 100644 tests/example-config.yaml
diff --git a/examples/__init__.py b/examples/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/example-config.yaml b/tests/example-config.yaml
new file mode 100644
index 0000000..adff316
--- /dev/null
+++ b/tests/example-config.yaml
@@ -0,0 +1,10 @@
+projects:
+ - name: default
+ userId: user123
+ token: pass123
+ url: https://api.gridscale.io
+
+ - name: something-else
+ userId: user456
+ token: pass456
+ url: https://api.gridscale.io
diff --git a/tests/test_config.py b/tests/test_config.py
index d5ceaab..3e288b9 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -1,5 +1,10 @@
+import os.path
+
from gs_api_client import Configuration
+from examples.configloader import load_config
+
+CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
def test_debug_is_disabled_by_default():
config = Configuration()
@@ -9,3 +14,14 @@ def test_debug_is_disabled_by_default():
def test_tls_certs_are_verified_by_default():
config = Configuration()
assert config.verify_ssl
+
+
+def test_load_config_from_yaml():
+ """"Make sure we can load a config from a given YAML file."""
+
+ example_config = os.path.join(CURRENT_DIR, "example-config.yaml")
+ res = load_config(example_config)
+ assert isinstance(res, list)
+ assert len(res) == 2
+ assert res[0]["name"] == "default"
+ assert res[1]["name"] == "something-else"
From 05c3775568c142f17aabc48e1407f86be8a14ea2 Mon Sep 17 00:00:00 2001
From: jonathanlutterbeck
<48634262+jonathanlutterbeck@users.noreply.github.com>
Date: Fri, 22 Apr 2022 11:27:59 +0200
Subject: [PATCH 04/11] Update dev-requirements.txt
added yaml import
---
dev-requirements.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/dev-requirements.txt b/dev-requirements.txt
index d8b1b8f..ebc6e29 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -7,3 +7,4 @@ rope
black
pytest
pytest-mock
+yaml
From 415112c2d30c7407f1aaa4708ed28af2fa4b73a5 Mon Sep 17 00:00:00 2001
From: Jonathan Lutterbeck
Date: Mon, 25 Apr 2022 19:15:34 +0200
Subject: [PATCH 05/11] Improve code to run checks
The tests now are green. I just changed it to return the contents of the yaml file.
In the test no path has to be passed. This is already done in the configloader. Can I remove this from the test @bkircher ?
---
examples/configloader.py | 47 +++++++++-------------------------------
examples/examples.py | 11 ++++++----
2 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/examples/configloader.py b/examples/configloader.py
index 75bccce..fc8d98f 100644
--- a/examples/configloader.py
+++ b/examples/configloader.py
@@ -26,7 +26,7 @@ def which_path():
if not os.path.exists(path):
os.makedirs(path)
else:
- "Operating System not supported"
+ print("Operating System not supported")
return path
@@ -35,45 +35,18 @@ def create_config(path):
shutil.copyfile(f"{cwd}/config.yaml", path)
print(f"New config file created, edit config file at: {path}")
-def load_config(projectname, goal, path):
- with open(f"{path}", 'r') as stream:
- try:
- data = yaml.safe_load(stream)
-
- for value in data.values():
- for x in range(len(value)):
- result = value[x]
- #returns userID and token for the selected project
- if (result.get("name") == projectname):
- userid = result.get("userId")
- token = result.get("token")
- except yaml.YAMLError as exc:
- print(exc)
-
- if(goal == "id"):
- return userid
- elif(goal == "token"):
- return token
-
-def load_token(project):
+def load_config(path):
syspath = which_path() + "/config.yaml"
- goal = "token"
- # check if config file exists
if not os.path.exists(syspath):
create_config(syspath)
- return load_config(project, goal, syspath)
- else:
- return load_config(project, goal, syspath)
-
-def load_userid(project):
- syspath = which_path() + "/config.yaml"
- goal = "id"
+ with open(f"{syspath}", 'r') as stream:
+ try:
+ data = yaml.safe_load(stream)
+ #return list of dictionaries for all projects
+ for value in data.values():
+ return(value)
- # check if config file exists
- if not os.path.exists(syspath):
- create_config(syspath)
- return load_config(project, goal, syspath)
- else:
- return load_config(project, goal, syspath)
+ except yaml.YAMLError as exc:
+ print(exc)
diff --git a/examples/examples.py b/examples/examples.py
index 9a1a572..c55ee06 100644
--- a/examples/examples.py
+++ b/examples/examples.py
@@ -2,13 +2,15 @@
from pprint import pprint
from uuid import uuid4
+import os
from index_by.key import index_by_key
-from configloader import load_token, load_userid
+from configloader import load_config
from gs_api_client import SyncGridscaleApiClient, GridscaleApiClient, models
from gs_api_client import Configuration
+CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
if __name__ == '__main__':
@@ -19,9 +21,10 @@
api_config.host = 'https://api.gridscale.io'
#TODO: Change project
- project = "default"
- api_config.api_key['X-Auth-Token'] = load_token(project)
- api_config.api_key['X-Auth-UserId'] = load_userid(project)
+ example_config = os.path.join(CURRENT_DIR, "config.yaml")
+ configfile = load_config(example_config)
+ api_config.api_key['X-Auth-Token'] = configfile[0].get("token")
+ api_config.api_key['X-Auth-UserId'] = configfile[0].get("userId")
api_config.debug = True
print('-' * 80)
From 6aed0110df2dc3e4ea5ca413d745e878ba1c743b Mon Sep 17 00:00:00 2001
From: jonathanlutterbeck
<48634262+jonathanlutterbeck@users.noreply.github.com>
Date: Mon, 25 Apr 2022 19:39:26 +0200
Subject: [PATCH 06/11] Changed yaml to pyyaml
Added misssing dependency pyyaml for pytest
---
dev-requirements.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dev-requirements.txt b/dev-requirements.txt
index ebc6e29..2a221be 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -7,4 +7,4 @@ rope
black
pytest
pytest-mock
-yaml
+pyyaml
From d7d1915fbfedfd157ef424967d8402a602931de6 Mon Sep 17 00:00:00 2001
From: Jonathan Lutterbeck
Date: Mon, 25 Apr 2022 19:41:45 +0200
Subject: [PATCH 07/11] Fixed error
The function was copying the file to the wrong location
---
examples/configloader.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/examples/configloader.py b/examples/configloader.py
index fc8d98f..84c6522 100644
--- a/examples/configloader.py
+++ b/examples/configloader.py
@@ -32,8 +32,8 @@ def which_path():
def create_config(path):
cwd = os.getcwd()
- shutil.copyfile(f"{cwd}/config.yaml", path)
- print(f"New config file created, edit config file at: {path}")
+ shutil.copyfile(f"{cwd}/config.yaml", syspath)
+ print(f"New config file created, edit config file at: {syspath}")
def load_config(path):
syspath = which_path() + "/config.yaml"
From a65854313d337bd2b404cc0a0046e5d1ff26fe45 Mon Sep 17 00:00:00 2001
From: Benjamin Kircher
Date: Wed, 27 Apr 2022 09:18:58 +0200
Subject: [PATCH 08/11] tests: Add more test cases for load_config()
---
tests/test_config.py | 39 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 38 insertions(+), 1 deletion(-)
diff --git a/tests/test_config.py b/tests/test_config.py
index 3e288b9..d6149b1 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -1,11 +1,14 @@
import os.path
+import pytest
+
from gs_api_client import Configuration
from examples.configloader import load_config
CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
+
def test_debug_is_disabled_by_default():
config = Configuration()
assert not config.debug
@@ -17,11 +20,45 @@ def test_tls_certs_are_verified_by_default():
def test_load_config_from_yaml():
- """"Make sure we can load a config from a given YAML file."""
+ """Make sure we can load a config from a given YAML file."""
example_config = os.path.join(CURRENT_DIR, "example-config.yaml")
res = load_config(example_config)
assert isinstance(res, list)
assert len(res) == 2
+ assert isinstance(res[0], dict)
assert res[0]["name"] == "default"
assert res[1]["name"] == "something-else"
+
+
+def test_load_config_handles_non_existing_file():
+ """ "Ensure load_config raises FileNotFoundError."""
+
+ with pytest.raises(FileNotFoundError):
+ load_config("fufu.yaml")
+
+
+def test_load_config_checks_for_bogus_input():
+ """ "Ensure load_config checks it's input."""
+
+ with pytest.raises(AssertionError):
+ load_config(42)
+
+ with pytest.raises(AssertionError):
+ load_config("")
+
+
+def test_load_config_propagates_parsing_errors():
+ """ "Ensure load_config raises any error during parsing."""
+
+ import yaml
+
+ not_a_yaml_file = os.path.join(CURRENT_DIR, "test_config.py")
+ with pytest.raises(yaml.YAMLError):
+ load_config(not_a_yaml_file)
+
+
+def test_load_config_has_doc_string():
+ """ "Make sure load_config is documented."""
+
+ assert load_config.__doc__
From 5fe3df0963e5c79d1e3b525dbe53fe4536c2d9a5 Mon Sep 17 00:00:00 2001
From: Jonathan Lutterbeck
Date: Mon, 25 Apr 2022 19:45:13 +0200
Subject: [PATCH 09/11] improvements to check validity of config file
Checks have been added to verify file name lenght and to check if it's really a .yaml file.
All tests are now green.
Fixed error
Moved the syspath cariable to be globally available
Fix error
path variable was named wrong
Try to fix github action error
Changed file name for config file.
Fixed Test
Fixed copyfile for test case
Check if config is valid
load_config now gives correct error messages and does not catch any exceptions.
The functions are now also properly seperated.
removed print statements
Print statements have been removed and replaced them with RuntimeErrors where applicable.
which_path was renamed to default_config_path.
Improved code
I merged the two isInstance calls to improve readability.
---
examples/configloader.py | 48 ++++++++++++++++++++++++----------------
examples/examples.py | 7 ++----
2 files changed, 31 insertions(+), 24 deletions(-)
diff --git a/examples/configloader.py b/examples/configloader.py
index 84c6522..4f01d3f 100644
--- a/examples/configloader.py
+++ b/examples/configloader.py
@@ -1,12 +1,17 @@
import shutil
import sys
import os.path
+import pathlib
import yaml
-#TODO: change active project
-project = "somthing-else"
-def which_path():
+def default_config_path():
+ """
+
+ this checks the operation system of the user.
+ this is used to determine the standard save location for the global gridscale config file.
+
+ """
#check if os is linux
if(sys.platform in ("linux", "linux2")):
path = "~/.config/gridscale"
@@ -26,27 +31,32 @@ def which_path():
if not os.path.exists(path):
os.makedirs(path)
else:
- print("Operating System not supported")
+ raise RuntimeError("Operating system not supported")
return path
-def create_config(path):
- cwd = os.getcwd()
- shutil.copyfile(f"{cwd}/config.yaml", syspath)
- print(f"New config file created, edit config file at: {syspath}")
-def load_config(path):
- syspath = which_path() + "/config.yaml"
+def create_config(path):
+ """
+ this will copy the currently used config file in the standard folder
+ """
+ syspath = default_config_path() + "/config.yaml"
+ shutil.copyfile(path, syspath)
- if not os.path.exists(syspath):
- create_config(syspath)
- with open(f"{syspath}", 'r') as stream:
- try:
+def load_config(path):
+ """
+ First checking "path" to match minimum length and other requirements.
+
+ Then it opens the specified config file and returns all keys which include token and UserId.
+ """
+ # opens specified file to retrieve config tokens
+ if isinstance(path, (pathlib.Path, str)):
+ assert path
+ with open(f"{path}", 'r') as stream:
data = yaml.safe_load(stream)
- #return list of dictionaries for all projects
+ # return list of dictionaries for all projects
for value in data.values():
- return(value)
-
- except yaml.YAMLError as exc:
- print(exc)
+ return (value)
+ else:
+ raise AssertionError
diff --git a/examples/examples.py b/examples/examples.py
index c55ee06..2dc1f03 100644
--- a/examples/examples.py
+++ b/examples/examples.py
@@ -10,8 +10,6 @@
from gs_api_client import Configuration
-CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
-
if __name__ == '__main__':
# run `pip3 install index_by` before executing this file
@@ -20,9 +18,8 @@
# api_config.debug = True
api_config.host = 'https://api.gridscale.io'
- #TODO: Change project
- example_config = os.path.join(CURRENT_DIR, "config.yaml")
- configfile = load_config(example_config)
+ #TODO: Change filename
+ configfile = load_config("config.yaml")
api_config.api_key['X-Auth-Token'] = configfile[0].get("token")
api_config.api_key['X-Auth-UserId'] = configfile[0].get("userId")
api_config.debug = True
From ebc5df8c4bd4c17bc0763badcef35ce208d5303e Mon Sep 17 00:00:00 2001
From: Benjamin Kircher
Date: Wed, 4 May 2022 10:05:50 +0200
Subject: [PATCH 10/11] tests: Ensure load_config does not interpret file name
---
tests/test_config.py | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/tests/test_config.py b/tests/test_config.py
index d6149b1..d267bee 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -1,4 +1,5 @@
import os.path
+import shutil
import pytest
@@ -31,6 +32,17 @@ def test_load_config_from_yaml():
assert res[1]["name"] == "something-else"
+def test_load_config_works_without_fileext(tmp_path):
+ """Ensure load_config does not interpret file path or file name."""
+
+ example_config = os.path.join(CURRENT_DIR, "example-config.yaml")
+ dest = tmp_path / "a"
+ shutil.copyfile(example_config, dest)
+ res = load_config(dest)
+ assert isinstance(res, list)
+ assert len(res) == 2
+
+
def test_load_config_handles_non_existing_file():
""" "Ensure load_config raises FileNotFoundError."""
From cf0f7396a5ce7e62e574da0e2d4396df99a152c1 Mon Sep 17 00:00:00 2001
From: "Jonathan, Lutterbeck"
Date: Thu, 2 Jun 2022 18:15:08 +0200
Subject: [PATCH 11/11] Squashed commit of the following:
commit ebc5df8c4bd4c17bc0763badcef35ce208d5303e
Author: Benjamin Kircher
Date: Wed May 4 10:05:50 2022 +0200
tests: Ensure load_config does not interpret file name
commit 5fe3df0963e5c79d1e3b525dbe53fe4536c2d9a5
Author: Jonathan Lutterbeck
Date: Mon Apr 25 19:45:13 2022 +0200
improvements to check validity of config file
Checks have been added to verify file name lenght and to check if it's really a .yaml file.
All tests are now green.
Fixed error
Moved the syspath cariable to be globally available
Fix error
path variable was named wrong
Try to fix github action error
Changed file name for config file.
Fixed Test
Fixed copyfile for test case
Check if config is valid
load_config now gives correct error messages and does not catch any exceptions.
The functions are now also properly seperated.
removed print statements
Print statements have been removed and replaced them with RuntimeErrors where applicable.
which_path was renamed to default_config_path.
Improved code
I merged the two isInstance calls to improve readability.
commit a65854313d337bd2b404cc0a0046e5d1ff26fe45
Author: Benjamin Kircher
Date: Wed Apr 27 09:18:58 2022 +0200
tests: Add more test cases for load_config()
commit 3566688a3c8b090437c52523d8f9fe08365a8f54
Merge: d7d1915 6aed011
Author: Jonathan Lutterbeck
Date: Mon Apr 25 19:42:41 2022 +0200
Merge branch 'enhancement/20-allow-reading-and-writing-shared-config-file' of https://github.com/gridscale/gridscale_api_client_python into enhancement/20-allow-reading-and-writing-shared-config-file
commit d7d1915fbfedfd157ef424967d8402a602931de6
Author: Jonathan Lutterbeck
Date: Mon Apr 25 19:41:45 2022 +0200
Fixed error
The function was copying the file to the wrong location
commit 6aed0110df2dc3e4ea5ca413d745e878ba1c743b
Author: jonathanlutterbeck <48634262+jonathanlutterbeck@users.noreply.github.com>
Date: Mon Apr 25 19:39:26 2022 +0200
Changed yaml to pyyaml
Added misssing dependency pyyaml for pytest
commit 415112c2d30c7407f1aaa4708ed28af2fa4b73a5
Author: Jonathan Lutterbeck
Date: Mon Apr 25 19:15:34 2022 +0200
Improve code to run checks
The tests now are green. I just changed it to return the contents of the yaml file.
In the test no path has to be passed. This is already done in the configloader. Can I remove this from the test @bkircher ?
commit 05c3775568c142f17aabc48e1407f86be8a14ea2
Author: jonathanlutterbeck <48634262+jonathanlutterbeck@users.noreply.github.com>
Date: Fri Apr 22 11:27:59 2022 +0200
Update dev-requirements.txt
added yaml import
commit 2c620621beae4eaa65a77500c68198e17bda6b53
Author: Benjamin Kircher
Date: Fri Apr 22 11:12:10 2022 +0200
Add test case for load_config
Add a test case that loads a simple YAML file with two projects. You can
run tests by executing `pytest` in the project root. Note that the test
currently fails.
commit 09ef4af0001ce24eabaf44f0dc47de10df9622f5
Author: jonathanlutterbeck <48634262+jonathanlutterbeck@users.noreply.github.com>
Date: Fri Apr 15 20:34:34 2022 +0200
improved code
added suggestions from pylint
commit acb07f79e4526a67225c027a3b7a9c099dcd1b49
Author: jonathanlutterbeck <48634262+jonathanlutterbeck@users.noreply.github.com>
Date: Fri Apr 15 15:34:24 2022 +0200
created configloader.py
added a configuration loader which checks for existing config files.
If the folder is not found it is created.
If the file is not found the default empty config file is copied to users home directory.
---
.idea/.gitignore | 3 +
.idea/gridscale_api_client_python.iml | 15 +++++
.idea/inspectionProfiles/Project_Default.xml | 20 ++++++
.../inspectionProfiles/profiles_settings.xml | 6 ++
.idea/misc.xml | 4 ++
.idea/modules.xml | 8 +++
.idea/vcs.xml | 6 ++
dev-requirements.txt | 1 +
examples/__init__.py | 0
examples/config.yaml | 9 +++
examples/configloader.py | 62 ++++++++++++++++++
examples/examples.py | 13 ++--
tests/example-config.yaml | 10 +++
tests/test_config.py | 65 +++++++++++++++++++
14 files changed, 217 insertions(+), 5 deletions(-)
create mode 100644 .idea/.gitignore
create mode 100644 .idea/gridscale_api_client_python.iml
create mode 100644 .idea/inspectionProfiles/Project_Default.xml
create mode 100644 .idea/inspectionProfiles/profiles_settings.xml
create mode 100644 .idea/misc.xml
create mode 100644 .idea/modules.xml
create mode 100644 .idea/vcs.xml
create mode 100644 examples/__init__.py
create mode 100644 examples/config.yaml
create mode 100644 examples/configloader.py
create mode 100644 tests/example-config.yaml
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/gridscale_api_client_python.iml b/.idea/gridscale_api_client_python.iml
new file mode 100644
index 0000000..14273e4
--- /dev/null
+++ b/.idea/gridscale_api_client_python.iml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..bc85450
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..5706053
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..52045b0
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dev-requirements.txt b/dev-requirements.txt
index d8b1b8f..2a221be 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -7,3 +7,4 @@ rope
black
pytest
pytest-mock
+pyyaml
diff --git a/examples/__init__.py b/examples/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/examples/config.yaml b/examples/config.yaml
new file mode 100644
index 0000000..9f7be7d
--- /dev/null
+++ b/examples/config.yaml
@@ -0,0 +1,9 @@
+projects:
+- name: default
+ userId: user123
+ token: pass123
+ url: https://api.gridscale.io
+- name: something-else
+ userId: user456
+ token: pass456
+ url: https://api.gridscale.io
\ No newline at end of file
diff --git a/examples/configloader.py b/examples/configloader.py
new file mode 100644
index 0000000..4f01d3f
--- /dev/null
+++ b/examples/configloader.py
@@ -0,0 +1,62 @@
+import shutil
+import sys
+import os.path
+import pathlib
+import yaml
+
+
+def default_config_path():
+ """
+
+ this checks the operation system of the user.
+ this is used to determine the standard save location for the global gridscale config file.
+
+ """
+ #check if os is linux
+ if(sys.platform in ("linux", "linux2")):
+ path = "~/.config/gridscale"
+ path = os.path.expanduser(path)
+ if not os.path.exists(path):
+ os.makedirs(path)
+ #check if os is windows
+ elif(sys.platform in ("win32", "cygwin", "msys")):
+ path = "%APPDATA%\gridscale"
+ path = os.path.expanduser(path)
+ if not os.path.exists(path):
+ os.makedirs(path)
+ #check if os is mac os
+ elif(sys.platform in ("darwin", "os2", "os2emx")):
+ path = "~/Library/Application Support/gridscale"
+ path = os.path.expanduser(path)
+ if not os.path.exists(path):
+ os.makedirs(path)
+ else:
+ raise RuntimeError("Operating system not supported")
+
+ return path
+
+
+def create_config(path):
+ """
+ this will copy the currently used config file in the standard folder
+ """
+ syspath = default_config_path() + "/config.yaml"
+ shutil.copyfile(path, syspath)
+
+
+def load_config(path):
+ """
+ First checking "path" to match minimum length and other requirements.
+
+ Then it opens the specified config file and returns all keys which include token and UserId.
+ """
+ # opens specified file to retrieve config tokens
+ if isinstance(path, (pathlib.Path, str)):
+ assert path
+ with open(f"{path}", 'r') as stream:
+ data = yaml.safe_load(stream)
+ # return list of dictionaries for all projects
+ for value in data.values():
+ return (value)
+ else:
+ raise AssertionError
diff --git a/examples/examples.py b/examples/examples.py
index e29f7c8..2dc1f03 100644
--- a/examples/examples.py
+++ b/examples/examples.py
@@ -2,7 +2,9 @@
from pprint import pprint
from uuid import uuid4
+import os
from index_by.key import index_by_key
+from configloader import load_config
from gs_api_client import SyncGridscaleApiClient, GridscaleApiClient, models
from gs_api_client import Configuration
@@ -16,11 +18,12 @@
# api_config.debug = True
api_config.host = 'https://api.gridscale.io'
- #TODO: Insert your API token and User ID
- api_config.api_key['X-Auth-Token'] = "AUTH_TOKEN"
- api_config.api_key['X-Auth-UserId'] = "USER_UUID"
- # api_config.debug = True
-
+ #TODO: Change filename
+ configfile = load_config("config.yaml")
+ api_config.api_key['X-Auth-Token'] = configfile[0].get("token")
+ api_config.api_key['X-Auth-UserId'] = configfile[0].get("userId")
+ api_config.debug = True
+
print('-' * 80)
client = SyncGridscaleApiClient(configuration=api_config, http_info=False)
diff --git a/tests/example-config.yaml b/tests/example-config.yaml
new file mode 100644
index 0000000..adff316
--- /dev/null
+++ b/tests/example-config.yaml
@@ -0,0 +1,10 @@
+projects:
+ - name: default
+ userId: user123
+ token: pass123
+ url: https://api.gridscale.io
+
+ - name: something-else
+ userId: user456
+ token: pass456
+ url: https://api.gridscale.io
diff --git a/tests/test_config.py b/tests/test_config.py
index d5ceaab..d267bee 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -1,4 +1,13 @@
+import os.path
+import shutil
+
+import pytest
+
from gs_api_client import Configuration
+from examples.configloader import load_config
+
+
+CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
def test_debug_is_disabled_by_default():
@@ -9,3 +18,59 @@ def test_debug_is_disabled_by_default():
def test_tls_certs_are_verified_by_default():
config = Configuration()
assert config.verify_ssl
+
+
+def test_load_config_from_yaml():
+ """Make sure we can load a config from a given YAML file."""
+
+ example_config = os.path.join(CURRENT_DIR, "example-config.yaml")
+ res = load_config(example_config)
+ assert isinstance(res, list)
+ assert len(res) == 2
+ assert isinstance(res[0], dict)
+ assert res[0]["name"] == "default"
+ assert res[1]["name"] == "something-else"
+
+
+def test_load_config_works_without_fileext(tmp_path):
+ """Ensure load_config does not interpret file path or file name."""
+
+ example_config = os.path.join(CURRENT_DIR, "example-config.yaml")
+ dest = tmp_path / "a"
+ shutil.copyfile(example_config, dest)
+ res = load_config(dest)
+ assert isinstance(res, list)
+ assert len(res) == 2
+
+
+def test_load_config_handles_non_existing_file():
+ """ "Ensure load_config raises FileNotFoundError."""
+
+ with pytest.raises(FileNotFoundError):
+ load_config("fufu.yaml")
+
+
+def test_load_config_checks_for_bogus_input():
+ """ "Ensure load_config checks it's input."""
+
+ with pytest.raises(AssertionError):
+ load_config(42)
+
+ with pytest.raises(AssertionError):
+ load_config("")
+
+
+def test_load_config_propagates_parsing_errors():
+ """ "Ensure load_config raises any error during parsing."""
+
+ import yaml
+
+ not_a_yaml_file = os.path.join(CURRENT_DIR, "test_config.py")
+ with pytest.raises(yaml.YAMLError):
+ load_config(not_a_yaml_file)
+
+
+def test_load_config_has_doc_string():
+ """ "Make sure load_config is documented."""
+
+ assert load_config.__doc__