Skip to content

Commit

Permalink
Remove depreciated stringify() method
Browse files Browse the repository at this point in the history
  • Loading branch information
eugenetriguba committed Nov 5, 2023
1 parent f42ad9e commit 3f874d1
Show file tree
Hide file tree
Showing 14 changed files with 86 additions and 88 deletions.
26 changes: 16 additions & 10 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Replaced deprecated use of `ruamel.yaml` methods in the YAML parser (via [#28](https://github.com/eugenetriguba/config-file/pull/28), thanks [@JaWeRn](https://github.com/JaWeRn)).

### Removed

- Depreciated `stringify()` method on `ConfigFile`. Use `str()`
on the `ConfigFile` instead.

## 0.12.0 - 2020-10-03

### Added

- Python's built-in `in` keyword now works with a ConfigFile.
- Python's built-in `in` keyword now works with a ConfigFile.

Example:

Example:
```python
config = ConfigFile('./pyproject.toml')
```python
config = ConfigFile('./pyproject.toml')

'tool.poetry' in config
>>> True
```
'tool.poetry' in config
>>> True
```

### Changed

- Depreciated `stringify()` in favor of just using the built-in `str()`.
- Depreciated `stringify()` in favor of just using the built-in `str()`.

### Fixed

- Addresses issue #25 (INI parser isn't converting back to string).
- Addresses issue #25 (INI parser isn't converting back to string).

## 0.11.0 - 2020-08-07

Expand Down Expand Up @@ -232,4 +238,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## 0.1.0 - 2020-01-04

- Initial Release
- Initial Release
5 changes: 0 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -299,11 +299,6 @@ built-in `str()` method on the ConfigFile. This will always show us our latest c
str(config)
>>> '[section]\nnum_key = 5\nstr_key = blah\nbool_key = true\nlist_key = [1, 2]\n\n[second_section]\ndict_key = { "another_num": 5 }\n\n'

# Depreciated but also works.
config.stringify()
>>> '[section]\nnum_key = 5\nstr_key = blah\nbool_key = true\nlist_key = [1, 2]\n\n[second_section]\ndict_key = { "another_num": 5 }\n\n'
```


### Using `restore_original()`

Expand Down
20 changes: 4 additions & 16 deletions config_file/config_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ def __contains__(self, key: str) -> bool:
return self.has(key)

def __str__(self) -> str:
return self.stringify()
return str(self.__parser)

def __repr__(self) -> str:
return f"{self.path}\n\n{self.stringify()}"
return f"{self.path}\n\n{str(self.__parser)}"

def get(
self,
Expand Down Expand Up @@ -85,7 +85,7 @@ def get(
key_value = self.__parser.get(key)
except KeyError as error:
if isinstance(default, Default) and default.value is None:
raise KeyError(error)
raise error
else:
key_value = default

Expand Down Expand Up @@ -125,18 +125,6 @@ def delete(self, key: str) -> None:
"""
self.__parser.delete(key)

def stringify(self) -> str:
"""Retrieves file contents as a string.
Returns:
The internal representation of the file
that has been read in converted to a string.
Depreciated:
Use str() on the ConfigFile object instead.
"""
return self.__parser.stringify()

def has(self, key: str, wild: bool = False) -> bool:
"""
Check if a section, sub-section, or key exists.
Expand Down Expand Up @@ -198,4 +186,4 @@ def save(self) -> None:
object's constructor.
"""
with open(str(self.__path), "w") as config_file:
config_file.write(self.stringify())
config_file.write(str(self))
2 changes: 0 additions & 2 deletions config_file/nested_lookup.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@ def get_occurrence_of_value(dictionary, value):


def _recursion(dictionary, item, keyword, occurrence, with_values=False):

global values_list

if item == "key":
Expand Down Expand Up @@ -380,7 +379,6 @@ def _nested_alter(
in_place,
key_len,
):

# return data if no callback_function is provided
if callback_function is None:
warnings.warn("Please provide a callback_function to nested_alter().")
Expand Down
5 changes: 3 additions & 2 deletions config_file/parsers/abstract_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,9 @@ def delete(self, key: str) -> None:
raise NotImplementedError

@abstractmethod
def stringify(self) -> str:
"""Stringify the working file.
def __str__(self) -> str:
"""
Stringify the working file.
Since the ConfigFile does not write out to disk
after every operation, this method is what is
Expand Down
83 changes: 51 additions & 32 deletions config_file/parsers/base_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@

class BaseParser(AbstractParser):
def __init__(self, file_contents: str):
"""The BaseParser implements the AbstractParser for us, as long as the
"""
The BaseParser implements the AbstractParser for us, as long as the
subclasses implement `loads`, `dumps`, and `decode_error` methods.
Internally, every parser uses the BaseParser so it does not
Expand All @@ -28,14 +29,15 @@ def __init__(self, file_contents: str):

@abstractmethod
def loads(self, contents: str) -> dict:
"""Transforms the file contents into a dictionary.
"""
Transforms the file contents into a dictionary.
Args:
contents: The file contents to transform.
Raises:
self.decode_error: If there is a decoding error
while attempting to parse the string.
while attempting to parse the string.
Returns:
The contents of a particular file as a dictionary
Expand All @@ -45,18 +47,18 @@ def loads(self, contents: str) -> dict:

@abstractmethod
def dumps(self, loaded_contents: dict) -> str:
"""Transform the parsed contents back into a string.
"""
Transform the parsed contents back into a string.
Args:
loaded_contents: The file contents from a self.loads call.
It doesn't necessary need to be from a loads call, could just
be a valid dictionary for the given format, but that is the
typical usecase.
It doesn't necessary need to be from a loads call, could just
be a valid dictionary for the given format, but that is the
typical usecase.
Raises:
self.decode_error: If there is a decoding error
while attempting to transform the dict back into a string.
while attempting to transform the dict back into a string.
Returns:
The dictionary parsed back into a string.
Expand All @@ -66,7 +68,8 @@ def dumps(self, loaded_contents: dict) -> str:
@property
@abstractmethod
def decode_error(self) -> Type[Exception]:
"""The decoding error raised by the subclass on loads/dumps.
"""
The decoding error raised by the subclass on loads/dumps.
Returns:
The decoding error
Expand All @@ -77,13 +80,17 @@ def decode_error(self) -> Type[Exception]:
def parsed_content(self) -> dict:
return self.__parsed_content

def __str__(self) -> str:
return self.dumps(self.__parsed_content)

def parse_file_contents(self) -> dict:
"""Parse the file contents by running the `loads` method on the module.
"""
Parse the file contents by running the `loads` method on the module.
Args:
module: The module to use to parse the file.
decode_error: The error that is raised from the module if the file
cannot be decoded.
cannot be decoded.
Raises:
ParsingError: If the decode_error is raised while running `loads`.
Expand All @@ -97,7 +104,8 @@ def parse_file_contents(self) -> dict:
raise ParsingError(error)

def reset_internal_contents(self, file_contents: str) -> None:
"""Reset the file contents and parsed contents of the parser.
"""
Reset the file contents and parsed contents of the parser.
Args:
file_contents: The new file contents.
Expand All @@ -109,45 +117,59 @@ def reset_internal_contents(self, file_contents: str) -> None:
self.__parsed_content = self.parse_file_contents()

def get(self, search_key: str) -> Any:
key_causing_error = None
"""
Retrieve a key from the parsed content.
Args:
search_key: The key to search from in the
parsed content in a "dot" syntax.
i.e. "section.key"
Raises:
KeyError: If the key or one of the sections
we're subscripting into does not exist.
Returns:
The value of the key we're searching for.
"""
error_key = None

try:
if "." not in search_key:
key_causing_error = search_key
error_key = search_key
return self.__parsed_content[search_key]
else:
split_keys = split_on_dot(search_key)

content_reference = self.__parsed_content
parsed_content = self.__parsed_content
for key in split_keys:
key_causing_error = key
content_reference = content_reference[key]

error_key = key
parsed_content = parsed_content[key]
except (KeyError, TypeError):
raise KeyError(
f"cannot `get` {search_key} because "
f"{key_causing_error} is not subscriptable."
f"{error_key} is not subscriptable."
)

return content_reference
return parsed_content

def set(self, key: str, value: Any) -> None:
if "." not in key:
self.__parsed_content[key] = value
return

keys = split_on_dot(key)
content_reference = self.__parsed_content
parsed_content = self.__parsed_content
for index, key in enumerate(keys):
if index == len(keys) - 1:
content_reference[key] = value
parsed_content[key] = value
return

try:
content_reference = content_reference[key]
parsed_content = parsed_content[key]
except KeyError:
content_reference[key] = {}
content_reference = content_reference[key]
parsed_content[key] = {}
parsed_content = parsed_content[key]

def delete(self, key: str) -> None:
try:
Expand All @@ -157,19 +179,16 @@ def delete(self, key: str) -> None:
indexes = split_on_dot(key)
indexes_length = len(indexes)

content_reference = self.__parsed_content
parsed_content = self.__parsed_content
for index, key in enumerate(indexes):
if index == indexes_length - 1:
del content_reference[key]
del parsed_content[key]
break

content_reference = content_reference[key]
parsed_content = parsed_content[key]
except (KeyError, TypeError):
raise KeyError(f"The specified key '{key}' to delete was not found.")

def stringify(self) -> str:
return self.dumps(self.__parsed_content)

def has(self, search_key: str, wild: bool = False) -> bool:
if wild:
return get_occurrence_of_key(self.__parsed_content, key=search_key) > 0
Expand Down
4 changes: 2 additions & 2 deletions config_file/parsers/parse_value.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,9 @@ def strtobool(val):
'val' is anything else.
"""
val = val.lower()
if val in ('y', 'yes', 't', 'true', 'on', '1'):
if val in ("y", "yes", "t", "true", "on", "1"):
return 1
elif val in ('n', 'no', 'f', 'false', 'off', '0'):
elif val in ("n", "no", "f", "false", "off", "0"):
return 0
else:
raise ValueError("invalid truth value %r" % (val,))
Expand Down
3 changes: 3 additions & 0 deletions config_file/parsers/yaml_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,17 @@ def __init__(self, file_contents: str):
@property
def decode_error(self) -> Type[Exception]:
from ruamel.yaml import YAMLError

return YAMLError

def loads(self, contents: str) -> dict:
from ruamel.yaml import YAML

return YAML().load(contents)

def dumps(self, loaded_contents: dict) -> str:
from ruamel.yaml import YAML

buffer = StringIO()
YAML().dump(loaded_contents, buffer)
return buffer.getvalue()
6 changes: 3 additions & 3 deletions tests/test_abstract_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ def delete(self, section_key):
def has(self, section_key: str, wild: bool = False):
super().has(section_key)

def stringify(self):
super().stringify()
def __str__(self):
super().__str__()

def reset_internal_contents(self, file_contents: str) -> None:
super().reset_internal_contents(file_contents)
Expand Down Expand Up @@ -64,7 +64,7 @@ def test_that_base_parser_can_not_be_instantiated():
(ConcreteAbstractParser("").get, ("",)),
(ConcreteAbstractParser("").set, ("", "")),
(ConcreteAbstractParser("").delete, ("",)),
(ConcreteAbstractParser("").stringify, None),
(ConcreteAbstractParser("").__str__, None),
(ConcreteAbstractParser("").has, ("",)),
(ConcreteAbstractParser("").reset_internal_contents, ("",)),
(ConcreteAbstractParser("").parsed_content, None),
Expand Down
Loading

0 comments on commit 3f874d1

Please sign in to comment.