Skip to content

Commit ab36f84

Browse files
committed
Use Unix newlines when
1 parent 28f7edf commit ab36f84

File tree

2 files changed

+104
-12
lines changed

2 files changed

+104
-12
lines changed

domdf_python_tools/paths.py

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,10 @@
4040
import pathlib
4141
import shutil
4242
import stat
43-
import types
4443
from typing import IO, Any, Callable, Iterable, List, Optional
4544

4645
# this package
47-
from domdf_python_tools.typing import PathLike
46+
from domdf_python_tools.typing import JsonLibrary, PathLike
4847

4948
__all__ = [
5049
"append",
@@ -62,6 +61,8 @@
6261
"WindowsPathPlus",
6362
]
6463

64+
newline_default = object()
65+
6566

6667
def append(var: str, filename: PathLike, **kwargs) -> int:
6768
"""
@@ -297,6 +298,10 @@ class PathPlus(pathlib.Path):
297298
but cannot instantiate a WindowsPath on a POSIX system or vice versa.
298299
299300
.. versionadded:: 0.3.8
301+
302+
.. versionchanged:: 0.5.1
303+
304+
Defaults to Unix line endings (``LF``) on all platforms.
300305
"""
301306

302307
def __new__(cls, *args, **kwargs):
@@ -471,53 +476,67 @@ def open(
471476
buffering: int = -1,
472477
encoding: Optional[str] = "UTF-8",
473478
errors: Optional[str] = None,
474-
newline: Optional[str] = None,
479+
newline: Optional[str] = newline_default, # type: ignore
475480
) -> IO[Any]:
476481
"""
477482
Open the file pointed by this path and return a file object, as
478483
the built-in open() function does.
479484
480485
:param mode: The mode to open the file in.
481-
:default mode: ``"r"`` (read only)
486+
:default mode: ``'r'`` (read only)
482487
:type mode: str
483488
:param buffering:
484489
:type buffering: int
485490
:param encoding:
486491
:type encoding: str
487492
:param errors:
488493
:param newline:
494+
:default newline: `universal newlines <https://docs.python.org/3/glossary.html#term-universal-newlines>`__ for reading, Unix line endings (``LF``) for writing.
489495
490496
:return:
491497
492498
.. versionadded:: 0.3.8
499+
500+
.. versionchanged:: 0.5.1
501+
502+
Defaults to Unix line endings (``LF``) on all platforms.
493503
"""
494504

495505
if 'b' in mode:
496506
encoding = None
507+
newline = None
508+
509+
if newline is newline_default:
510+
if 'r' in mode:
511+
newline = None
512+
else:
513+
newline = "\n"
514+
497515
return super().open(mode, buffering=buffering, encoding=encoding, errors=errors, newline=newline)
498516

499517
def dump_json(
500518
self,
501519
data: Any,
502520
encoding: Optional[str] = "UTF-8",
503521
errors: Optional[str] = None,
504-
json_library: types.ModuleType = json,
522+
json_library: JsonLibrary = json, # type: ignore
505523
**kwargs,
506524
) -> int:
507525
"""
508-
Dump ``data`` to the file.
526+
Dump ``data`` to the file as JSON.
509527
510528
:param data: The object to serialise to JSON.
511529
:param encoding: The encoding to write to the file using.
512530
:param errors:
513531
:param json_library: The JSON serialisation library to use.
532+
:default json_library: :mod:`json`
514533
:param kwargs: Keyword arguments to pass to the JSON serialisation function.
515534
516535
.. versionadded:: 0.5.0
517536
"""
518537

519538
return self.write_text(
520-
json_library.dumps(data, **kwargs), # type: ignore
539+
json_library.dumps(data, **kwargs),
521540
encoding=encoding,
522541
errors=errors,
523542
)
@@ -526,7 +545,7 @@ def load_json(
526545
self,
527546
encoding: Optional[str] = "UTF-8",
528547
errors: Optional[str] = None,
529-
json_library: types.ModuleType = json,
548+
json_library: JsonLibrary = json, # type: ignore
530549
**kwargs,
531550
) -> Any:
532551
"""
@@ -535,14 +554,15 @@ def load_json(
535554
:param encoding: The encoding to write to the file using.
536555
:param errors:
537556
:param json_library: The JSON serialisation library to use.
557+
:default json_library: :mod:`json`
538558
:param kwargs: Keyword arguments to pass to the JSON deserialisation function.
539559
540560
:return: The deserialised JSON data.
541561
542562
.. versionadded:: 0.5.0
543563
"""
544564

545-
return json_library.loads( # type: ignore
565+
return json_library.loads(
546566
self.read_text(encoding=encoding, errors=errors),
547567
**kwargs,
548568
)

domdf_python_tools/typing.py

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,13 @@
2626
# stdlib
2727
import os
2828
import pathlib
29+
import sys
2930
from decimal import Decimal
30-
from typing import Any, Type, Union
31+
from json import JSONDecoder, JSONEncoder
32+
from types import ModuleType
33+
from typing import Any, Callable, Dict, List, Optional, Tuple, Type, Union
3134

32-
__all__ = ["PathLike", "AnyNumber", "check_membership"]
35+
__all__ = ["PathLike", "AnyNumber", "check_membership", "JsonLibrary"]
3336

3437
#: Type hint for objects that represent filesystem paths.
3538
PathLike = Union[str, pathlib.Path, os.PathLike]
@@ -46,7 +49,7 @@
4649

4750
def check_membership(obj: Any, type_: Union[Type, object]) -> bool:
4851
"""
49-
Check if the type of ``obj`` is one of the types in a :py:data:`typing.Union`, :typing.sequence:``Sequence`` etc.
52+
Check if the type of ``obj`` is one of the types in a :py:data:`typing.Union`, :typing.sequence:`Sequence` etc.
5053
5154
:param obj: The object to check the type of
5255
:param type_: A :class:`~typing.Type` that has members, such as a List, Union or Sequence.
@@ -56,3 +59,72 @@ def check_membership(obj: Any, type_: Union[Type, object]) -> bool:
5659
"""
5760

5861
return isinstance(obj, type_.__args__) # type: ignore
62+
63+
64+
class JsonLibrary(ModuleType):
65+
"""
66+
Type hint for functions that take a JSON serialisation-deserialisation library as an argument.
67+
68+
The library implement at least the following methods:
69+
"""
70+
71+
@staticmethod
72+
def dumps(
73+
obj: Any,
74+
*,
75+
skipkeys: bool = ...,
76+
ensure_ascii: bool = ...,
77+
check_circular: bool = ...,
78+
allow_nan: bool = ...,
79+
cls: Optional[Type[JSONEncoder]] = ...,
80+
indent: Union[None, int, str] = ...,
81+
separators: Optional[Tuple[str, str]] = ...,
82+
default: Optional[Callable[[Any], Any]] = ...,
83+
sort_keys: bool = ...,
84+
**kwds: Any,
85+
) -> str:
86+
"""
87+
Serialize ``obj`` to a JSON formatted ``str``.
88+
89+
:param obj:
90+
:param skipkeys:
91+
:param ensure_ascii:
92+
:param check_circular:
93+
:param allow_nan:
94+
:param cls:
95+
:param indent:
96+
:param separators:
97+
:param default:
98+
:param sort_keys:
99+
:param kwds:
100+
"""
101+
102+
if sys.version_info >= (3, 6):
103+
_LoadsString = Union[str, bytes]
104+
else:
105+
_LoadsString = str
106+
107+
@staticmethod
108+
def loads(
109+
s: _LoadsString,
110+
*,
111+
cls: Optional[Type[JSONDecoder]] = ...,
112+
object_hook: Optional[Callable[[Dict[Any, Any]], Any]] = ...,
113+
parse_float: Optional[Callable[[str], Any]] = ...,
114+
parse_int: Optional[Callable[[str], Any]] = ...,
115+
parse_constant: Optional[Callable[[str], Any]] = ...,
116+
object_pairs_hook: Optional[Callable[[List[Tuple[Any, Any]]], Any]] = ...,
117+
**kwds: Any,
118+
) -> Any:
119+
"""
120+
Deserialize ``s`` to a Python object.
121+
122+
:param s:
123+
:param cls:
124+
:param object_hook:
125+
:param parse_float:
126+
:param parse_int:
127+
:param parse_constant:
128+
:param object_pairs_hook:
129+
:param kwds:
130+
"""

0 commit comments

Comments
 (0)