Passed
Push — main ( 6e4731...702ebc )
by Douglas
02:44
created

WebResource._info_path()   A

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
import gzip
0 ignored issues
show
introduced by
Missing module docstring
Loading history...
2
import logging
3
import shutil
4
import zipfile
5
from datetime import datetime
6
from pathlib import Path
7
from typing import Mapping, Optional
8
from urllib import request
9
10
from pocketutils.core import PathLike
0 ignored issues
show
Bug introduced by
The name core does not seem to exist in module pocketutils.
Loading history...
introduced by
Cannot import 'pocketutils.core' due to syntax error 'invalid syntax (<unknown>, line 134)'
Loading history...
11
12
logger = logging.getLogger("pocketutils")
13
14
15
class WebResource:
16
    """
17
    Useful for extracting files from ZIP and GZIPing them.
18
    """
19
20
    def __init__(self, url: str, archive_member: Optional[str], local_path: PathLike):
21
        self._url = url
22
        self._archive_member = archive_member
23
        self._local_path = Path(local_path)
24
25
    def download(self, redownload: bool = False):
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
26
        now = datetime.now()
27
        to_path = Path(self._local_path)
28
        if not to_path.exists() or redownload:
29
            extracted, dled = None, None
30
            try:
31
                logger.info(f"Downloading {self._url}...")
0 ignored issues
show
introduced by
Use lazy % formatting in logging functions
Loading history...
32
                tmp = str(to_path) + now.strftime("%Y%m%d-%H%M%S-%f") + ".tmp"
33
                dled, response = request.urlretrieve(self._url, tmp)
34
                dled = Path(dled)
35
                if self._archive_member is not None:
36
                    with zipfile.ZipFile(dled, "r") as zfile:
37
                        extracted = Path(zfile.extract(self._archive_member))
38
                else:
39
                    extracted = dled
40
                if to_path.suffix == ".gz" and not self.__is_gzip(extracted):
41
                    with extracted.open("rb") as f_in:
42
                        with gzip.open(to_path, "wb") as f_out:
43
                            shutil.copyfileobj(f_in, f_out)
44
                else:
45
                    shutil.move(extracted, to_path)
46
                self._info_path.write_text(
47
                    "url="
48
                    + self._url
49
                    + "\n"
50
                    + "datetime_downloaded="
51
                    + now.isoformat()
52
                    + "\n"
53
                    + "response="
54
                    + str(response).replace("\n", " |")
55
                    + "\n",
56
                    encoding="utf-8",
57
                )
58
            finally:
59
                if extracted is not None and extracted.exists():
60
                    extracted.unlink()
61
                if dled is not None and dled.exists():
62
                    dled.unlink()
63
64
    def datetime_downloaded(self) -> datetime:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
65
        return datetime.fromisoformat(self.metadata()["datetime_downloaded"])
66
67
    def metadata(self) -> Mapping[str, str]:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
68
        return {
69
            line[: line.index("=")].strip(): line[line.index("=") + 1 :].strip()
70
            for line in self._info_path.read_text(encoding="utf8").splitlines()
71
        }
72
73
    @property
74
    def _info_path(self) -> Path:
75
        return self._local_path.with_suffix(self._local_path.suffix + ".info")
76
77
    def exists(self) -> bool:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
78
        return self._local_path.exists()
79
80
    @property
81
    def path(self) -> Path:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
82
        return self._local_path
83
84
    def delete(self) -> None:
0 ignored issues
show
introduced by
Missing function or method docstring
Loading history...
85
        self.path.unlink(missing_ok=True)
0 ignored issues
show
Bug introduced by
The keyword missing_ok does not seem to exist for the method call.
Loading history...
86
87
    def __is_gzip(self, path):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
88
        try:
89
            with gzip.open(path, "rb") as f:
0 ignored issues
show
Coding Style Naming introduced by
Variable name "f" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
90
                f.read(20)  # 10-byte header
91
        except OSError as e:
0 ignored issues
show
Coding Style Naming introduced by
Variable name "e" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
92
            if "Not a gzipped file" in str(e):
0 ignored issues
show
unused-code introduced by
Unnecessary "else" after "return"
Loading history...
93
                return False
94
            else:
95
                raise e
96
        return True
97
98
99
__all__ = ["WebResource"]
100