circup 2.0.1__py3-none-any.whl

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.
circup/bundle.py ADDED
@@ -0,0 +1,170 @@
1
+ # SPDX-FileCopyrightText: 2019 Nicholas Tollervey, 2024 Tim Cocks, written for Adafruit Industries
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ """
5
+ Class that represents a specific release of a Bundle.
6
+ """
7
+ import os
8
+ import sys
9
+
10
+ import click
11
+ import requests
12
+
13
+ from circup.shared import (
14
+ DATA_DIR,
15
+ PLATFORMS,
16
+ REQUESTS_TIMEOUT,
17
+ tags_data_load,
18
+ get_latest_release_from_url,
19
+ )
20
+
21
+ from circup.logging import logger
22
+
23
+
24
+ class Bundle:
25
+ """
26
+ All the links and file names for a bundle
27
+ """
28
+
29
+ def __init__(self, repo):
30
+ """
31
+ Initialise a Bundle created from its github info.
32
+ Construct all the strings in one place.
33
+
34
+ :param str repo: Repository string for github: "user/repository"
35
+ """
36
+ vendor, bundle_id = repo.split("/")
37
+ bundle_id = bundle_id.lower().replace("_", "-")
38
+ self.key = repo
39
+ #
40
+ self.url = "https://github.com/" + repo
41
+ self.basename = bundle_id + "-{platform}-{tag}"
42
+ self.urlzip = self.basename + ".zip"
43
+ self.dir = os.path.join(DATA_DIR, vendor, bundle_id + "-{platform}")
44
+ self.zip = os.path.join(DATA_DIR, bundle_id + "-{platform}.zip")
45
+ self.url_format = self.url + "/releases/download/{tag}/" + self.urlzip
46
+ # tag
47
+ self._current = None
48
+ self._latest = None
49
+
50
+ def lib_dir(self, platform):
51
+ """
52
+ This bundle's lib directory for the platform.
53
+
54
+ :param str platform: The platform identifier (py/6mpy/...).
55
+ :return: The path to the lib directory for the platform.
56
+ """
57
+ tag = self.current_tag
58
+ return os.path.join(
59
+ self.dir.format(platform=platform),
60
+ self.basename.format(platform=PLATFORMS[platform], tag=tag),
61
+ "lib",
62
+ )
63
+
64
+ def examples_dir(self, platform):
65
+ """
66
+ This bundle's examples directory for the platform.
67
+
68
+ :param str platform: The platform identifier (py/6mpy/...).
69
+ :return: The path to the examples directory for the platform.
70
+ """
71
+ tag = self.current_tag
72
+ return os.path.join(
73
+ self.dir.format(platform=platform),
74
+ self.basename.format(platform=PLATFORMS[platform], tag=tag),
75
+ "examples",
76
+ )
77
+
78
+ def requirements_for(self, library_name, toml_file=False):
79
+ """
80
+ The requirements file for this library.
81
+
82
+ :param str library_name: The name of the library.
83
+ :return: The path to the requirements.txt file.
84
+ """
85
+ platform = "py"
86
+ tag = self.current_tag
87
+ found_file = os.path.join(
88
+ self.dir.format(platform=platform),
89
+ self.basename.format(platform=PLATFORMS[platform], tag=tag),
90
+ "requirements",
91
+ library_name,
92
+ "requirements.txt" if not toml_file else "pyproject.toml",
93
+ )
94
+ if os.path.isfile(found_file):
95
+ with open(found_file, "r", encoding="utf-8") as read_this:
96
+ return read_this.read()
97
+ return None
98
+
99
+ @property
100
+ def current_tag(self):
101
+ """
102
+ Lazy load current cached tag from the BUNDLE_DATA json file.
103
+
104
+ :return: The current cached tag value for the project.
105
+ """
106
+ if self._current is None:
107
+ self._current = tags_data_load(logger).get(self.key, "0")
108
+ return self._current
109
+
110
+ @current_tag.setter
111
+ def current_tag(self, tag):
112
+ """
113
+ Set the current cached tag (after updating).
114
+
115
+ :param str tag: The new value for the current tag.
116
+ :return: The current cached tag value for the project.
117
+ """
118
+ self._current = tag
119
+
120
+ @property
121
+ def latest_tag(self):
122
+ """
123
+ Lazy find the value of the latest tag for the bundle.
124
+
125
+ :return: The most recent tag value for the project.
126
+ """
127
+ if self._latest is None:
128
+ self._latest = get_latest_release_from_url(
129
+ self.url + "/releases/latest", logger
130
+ )
131
+ return self._latest
132
+
133
+ def validate(self):
134
+ """
135
+ Test the existence of the expected URLs (not their content)
136
+ """
137
+ tag = self.latest_tag
138
+ if not tag or tag == "releases":
139
+ if "--verbose" in sys.argv:
140
+ click.secho(f' Invalid tag "{tag}"', fg="red")
141
+ return False
142
+ for platform in PLATFORMS.values():
143
+ url = self.url_format.format(platform=platform, tag=tag)
144
+ r = requests.get(url, stream=True, timeout=REQUESTS_TIMEOUT)
145
+ # pylint: disable=no-member
146
+ if r.status_code != requests.codes.ok:
147
+ if "--verbose" in sys.argv:
148
+ click.secho(f" Unable to find {os.path.split(url)[1]}", fg="red")
149
+ return False
150
+ # pylint: enable=no-member
151
+ return True
152
+
153
+ def __repr__(self):
154
+ """
155
+ Helps with log files.
156
+
157
+ :return: A repr of a dictionary containing the Bundles's metadata.
158
+ """
159
+ return repr(
160
+ {
161
+ "key": self.key,
162
+ "url": self.url,
163
+ "urlzip": self.urlzip,
164
+ "dir": self.dir,
165
+ "zip": self.zip,
166
+ "url_format": self.url_format,
167
+ "current": self._current,
168
+ "latest": self._latest,
169
+ }
170
+ )