typerconf 2.2__tar.gz → 2.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: typerconf
3
- Version: 2.2
3
+ Version: 2.3
4
4
  Summary: Library to read and write configs using API and CLI with Typer
5
5
  Home-page: https://github.com/dbosk/typerconf
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "typerconf"
3
- version = "2.2"
3
+ version = "2.3"
4
4
  description = "Library to read and write configs using API and CLI with Typer"
5
5
  authors = ["Daniel Bosk <daniel@bosk.se>"]
6
6
  license = "MIT"
@@ -16,7 +16,7 @@ dirs = appdirs.AppDirs(basename)
16
16
  class Config:
17
17
  """Navigates nested JSON structures by dot-separated addressing."""
18
18
 
19
- def __init__(self, json_data={},
19
+ def __init__(self, json_data=None,
20
20
  conf_file=None):
21
21
  """
22
22
  Constructs a config object to navigate from JSON data `json_data`.
@@ -30,7 +30,10 @@ class Config:
30
30
 
31
31
  To not enable write back, load file contents with the `.read_config` method.
32
32
  """
33
- self.__data = json_data
33
+ if not json_data:
34
+ self.__data = {}
35
+ else:
36
+ self.__data = json_data
34
37
  if isinstance(conf_file, io.IOBase):
35
38
  try:
36
39
  self.__conf_file = conf_file.name
@@ -123,14 +123,17 @@ Both work with these dot-separated addresses.
123
123
  class Config:
124
124
  """Navigates nested JSON structures by dot-separated addressing."""
125
125
 
126
- def __init__(self, json_data={},
126
+ def __init__(self, json_data=None,
127
127
  <<Config constructor args>>):
128
128
  """
129
129
  Constructs a config object to navigate from JSON data `json_data`.
130
130
 
131
131
  <<Config constructor args doc>>
132
132
  """
133
- self.__data = json_data
133
+ if not json_data:
134
+ self.__data = {}
135
+ else:
136
+ self.__data = json_data
134
137
  <<Config attributes>>
135
138
 
136
139
  <<Config methods for get and set>>
@@ -138,7 +141,27 @@ class Config:
138
141
  <<Config methods for reading from and writing to file>>
139
142
  @
140
143
 
141
- We will use the following test data for the test functions.
144
+ We want to test the constructor.
145
+ <<test functions>>=
146
+ def test_constructor():
147
+ test_key = "courses"
148
+ test_value = "test"
149
+
150
+ conf = Config(json_data={test_key: test_value})
151
+ assert test_key in conf.get()
152
+
153
+ assert test_key not in Config(json_data={}).get()
154
+ assert test_key not in Config().get()
155
+
156
+ conf = Config()
157
+ conf.set(test_key, test_value)
158
+ assert conf.get(test_key) == test_value
159
+
160
+ assert test_key not in Config().get()
161
+ @
162
+
163
+ We will use the following test data for the test functions in the remainder of
164
+ the text.
142
165
  <<test functions>>=
143
166
  test_data = {
144
167
  "courses": {
@@ -278,6 +301,16 @@ def test_set_path_list():
278
301
  assert gotten_value == value
279
302
  @
280
303
 
304
+ We also want to test short paths.
305
+ <<test functions>>=
306
+ def test_set_short_path():
307
+ value = "Test Tester"
308
+ path = "contact"
309
+ conf.set(path, value)
310
+
311
+ assert conf.get(path) == value
312
+ @
313
+
281
314
  When we want to remove a node, the pythonic way is to simply try to remove it.
282
315
  If it doesn't exist, we silently fail.
283
316
  The reasoning is as follows: the goal is to remove something; if it doesn't
@@ -306,6 +339,19 @@ def test_set_path_remove():
306
339
  assert False
307
340
  @
308
341
 
342
+ We also want to remove from a longer path.
343
+ <<test functions>>=
344
+ def test_set_path_list():
345
+ path = "courses.prgx22.TAs"
346
+ conf.set(path, None)
347
+ try:
348
+ conf.get(path)
349
+ except KeyError:
350
+ assert True
351
+ else:
352
+ assert False
353
+ @
354
+
309
355
  We want to traverse the tree, we want to go to the immediate parent of the leaf
310
356
  that we want to set a value for (or delete).
311
357
  We iterate through the path.
@@ -754,12 +800,14 @@ written to the file.
754
800
  <<test functions>>=
755
801
  def test_writeback_constructor():
756
802
  with tempfile.NamedTemporaryFile("w") as tmp_conf_file:
757
- tmp_conf_file_name = "/tmp/writeback" #tmp_conf_file.name
803
+ tmp_conf_file_name = tmp_conf_file.name
758
804
  path = "the.path"
759
805
  first_value = "1st"
760
806
  second_value = "2nd"
761
807
 
762
808
  initial_conf = Config()
809
+ assert initial_conf.get() == {}
810
+
763
811
  initial_conf.set(path, first_value)
764
812
  initial_conf.write_config(tmp_conf_file_name)
765
813
 
@@ -768,6 +816,8 @@ def test_writeback_constructor():
768
816
  conf.set(path, second_value)
769
817
 
770
818
  last_conf = Config()
819
+ assert last_conf.get() == {}
820
+
771
821
  last_conf.read_config(tmp_conf_file_name)
772
822
  assert last_conf.get(path) == second_value
773
823
  <<test imports>>=
@@ -921,6 +971,8 @@ if values == "":
921
971
  values = None
922
972
  @
923
973
 
974
+ \subsection{Testing the config command}
975
+
924
976
  Let's test this command.
925
977
  We'll set up the testing.
926
978
  <<test functions>>=
@@ -936,7 +988,7 @@ Let's look at the actual tests.
936
988
  <<run tests on [[cli]]>>=
937
989
  # set example data
938
990
  result = runner.invoke(cli,
939
- ["courses.datintro22.url", "--set", "https://..."])
991
+ ["courses.datintro22.url", "--set", "https://..."])
940
992
  assert result.exit_code == 0
941
993
 
942
994
  # try access nonexisting
@@ -949,7 +1001,7 @@ assert "courses.datintro22.url = https://..." in result.stdout
949
1001
 
950
1002
  # clear config
951
1003
  result = runner.invoke(cli,
952
- ["courses", "--set", None])
1004
+ ["courses", "--set", ""])
953
1005
  assert result.exit_code == 0
954
1006
 
955
1007
  # check that it's cleared
@@ -972,6 +1024,26 @@ def test_cli_not_default_conf():
972
1024
  <<run tests on [[cli]]>>
973
1025
  @
974
1026
 
1027
+ We'll do another round of tests, but this time for shorter paths.
1028
+ <<test functions>>=
1029
+ def test_short_paths():
1030
+ result = runner.invoke(cli, ["contact"])
1031
+ assert result.exit_code != 0
1032
+
1033
+ result = runner.invoke(cli,
1034
+ ["contact", "--set", "me"])
1035
+ assert result.exit_code == 0
1036
+
1037
+ result = runner.invoke(cli, ["contact"])
1038
+ assert "contact = me" in result.stdout
1039
+
1040
+ result = runner.invoke(cli,
1041
+ ["contact", "--set", ""])
1042
+ assert result.exit_code == 0
1043
+
1044
+ result = runner.invoke(cli, ["contact"])
1045
+ assert result.exit_code != 0
1046
+ @
975
1047
 
976
1048
  \subsection{Autocompleting the path}
977
1049
 
File without changes
File without changes
File without changes