circup 1.8.0__tar.gz → 1.9.0__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.
Files changed (78) hide show
  1. {circup-1.8.0/circup.egg-info → circup-1.9.0}/PKG-INFO +5 -5
  2. {circup-1.8.0 → circup-1.9.0}/circup/backends.py +62 -15
  3. {circup-1.8.0 → circup-1.9.0}/circup/command_utils.py +24 -13
  4. {circup-1.8.0 → circup-1.9.0}/circup/commands.py +1 -1
  5. {circup-1.8.0 → circup-1.9.0/circup.egg-info}/PKG-INFO +5 -5
  6. {circup-1.8.0 → circup-1.9.0}/tests/import_styles.py +1 -1
  7. {circup-1.8.0 → circup-1.9.0}/.github/ISSUE_TEMPLATE.md +0 -0
  8. {circup-1.8.0 → circup-1.9.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  9. {circup-1.8.0 → circup-1.9.0}/.github/workflows/build.yml +0 -0
  10. {circup-1.8.0 → circup-1.9.0}/.github/workflows/release.yml +0 -0
  11. {circup-1.8.0 → circup-1.9.0}/.gitignore +0 -0
  12. {circup-1.8.0 → circup-1.9.0}/.isort.cfg +0 -0
  13. {circup-1.8.0 → circup-1.9.0}/.pre-commit-config.yaml +0 -0
  14. {circup-1.8.0 → circup-1.9.0}/.pylintrc +0 -0
  15. {circup-1.8.0 → circup-1.9.0}/CODE_OF_CONDUCT.rst +0 -0
  16. {circup-1.8.0 → circup-1.9.0}/CODE_OF_CONDUCT.rst.license +0 -0
  17. {circup-1.8.0 → circup-1.9.0}/CONTRIBUTING.rst +0 -0
  18. {circup-1.8.0 → circup-1.9.0}/CONTRIBUTING.rst.license +0 -0
  19. {circup-1.8.0 → circup-1.9.0}/LICENSE +0 -0
  20. {circup-1.8.0 → circup-1.9.0}/LICENSES/CC-BY-4.0.txt +0 -0
  21. {circup-1.8.0 → circup-1.9.0}/LICENSES/MIT.txt +0 -0
  22. {circup-1.8.0 → circup-1.9.0}/LICENSES/Unlicense.txt +0 -0
  23. {circup-1.8.0 → circup-1.9.0}/README.rst +0 -0
  24. {circup-1.8.0 → circup-1.9.0}/README.rst.license +0 -0
  25. {circup-1.8.0 → circup-1.9.0}/circup/__init__.py +0 -0
  26. {circup-1.8.0 → circup-1.9.0}/circup/bundle.py +0 -0
  27. {circup-1.8.0 → circup-1.9.0}/circup/config/bundle_config.json +0 -0
  28. {circup-1.8.0 → circup-1.9.0}/circup/config/bundle_config.json.license +0 -0
  29. {circup-1.8.0 → circup-1.9.0}/circup/logging.py +0 -0
  30. {circup-1.8.0 → circup-1.9.0}/circup/module.py +0 -0
  31. {circup-1.8.0 → circup-1.9.0}/circup/shared.py +0 -0
  32. {circup-1.8.0 → circup-1.9.0}/circup.egg-info/SOURCES.txt +0 -0
  33. {circup-1.8.0 → circup-1.9.0}/circup.egg-info/dependency_links.txt +0 -0
  34. {circup-1.8.0 → circup-1.9.0}/circup.egg-info/entry_points.txt +0 -0
  35. {circup-1.8.0 → circup-1.9.0}/circup.egg-info/requires.txt +4 -4
  36. {circup-1.8.0 → circup-1.9.0}/circup.egg-info/top_level.txt +0 -0
  37. {circup-1.8.0 → circup-1.9.0}/docs/_static/favicon.ico +0 -0
  38. {circup-1.8.0 → circup-1.9.0}/docs/_static/favicon.ico.license +0 -0
  39. {circup-1.8.0 → circup-1.9.0}/docs/conf.py +0 -0
  40. {circup-1.8.0 → circup-1.9.0}/docs/index.rst +0 -0
  41. {circup-1.8.0 → circup-1.9.0}/docs/index.rst.license +0 -0
  42. {circup-1.8.0 → circup-1.9.0}/docs/logo.png +0 -0
  43. {circup-1.8.0 → circup-1.9.0}/docs/logo.png.license +0 -0
  44. {circup-1.8.0 → circup-1.9.0}/optional_requirements.txt +0 -0
  45. {circup-1.8.0 → circup-1.9.0}/optional_requirements.txt.license +0 -0
  46. {circup-1.8.0 → circup-1.9.0}/readthedocs.yml +0 -0
  47. {circup-1.8.0 → circup-1.9.0}/requirements.txt +0 -0
  48. {circup-1.8.0 → circup-1.9.0}/requirements.txt.license +0 -0
  49. {circup-1.8.0 → circup-1.9.0}/setup.cfg +0 -0
  50. {circup-1.8.0 → circup-1.9.0}/setup.py +0 -0
  51. {circup-1.8.0 → circup-1.9.0}/tests/__init__.py +0 -0
  52. {circup-1.8.0 → circup-1.9.0}/tests/bad_module/__init__.py +0 -0
  53. {circup-1.8.0 → circup-1.9.0}/tests/bad_module/my_module.py +0 -0
  54. {circup-1.8.0 → circup-1.9.0}/tests/bad_python.py +0 -0
  55. {circup-1.8.0 → circup-1.9.0}/tests/bundle.json +0 -0
  56. {circup-1.8.0 → circup-1.9.0}/tests/bundle.json.license +0 -0
  57. {circup-1.8.0 → circup-1.9.0}/tests/device.json +0 -0
  58. {circup-1.8.0 → circup-1.9.0}/tests/device.json.license +0 -0
  59. {circup-1.8.0 → circup-1.9.0}/tests/dir_module/__init__.py +0 -0
  60. {circup-1.8.0 → circup-1.9.0}/tests/dir_module/my_module.py +0 -0
  61. {circup-1.8.0 → circup-1.9.0}/tests/local_module.py +0 -0
  62. {circup-1.8.0 → circup-1.9.0}/tests/local_module_cp7.mpy +0 -0
  63. {circup-1.8.0 → circup-1.9.0}/tests/local_module_cp7.mpy.license +0 -0
  64. {circup-1.8.0 → circup-1.9.0}/tests/mock_device/boot_out.txt +0 -0
  65. {circup-1.8.0 → circup-1.9.0}/tests/mock_device/boot_out.txt.license +0 -0
  66. {circup-1.8.0 → circup-1.9.0}/tests/mock_device/lib/adafruit_waveform/.gitkeep +0 -0
  67. {circup-1.8.0 → circup-1.9.0}/tests/mount_exists.txt +0 -0
  68. {circup-1.8.0 → circup-1.9.0}/tests/mount_exists.txt.license +0 -0
  69. {circup-1.8.0 → circup-1.9.0}/tests/mount_missing.txt +0 -0
  70. {circup-1.8.0 → circup-1.9.0}/tests/mount_missing.txt.license +0 -0
  71. {circup-1.8.0 → circup-1.9.0}/tests/remote_module.py +0 -0
  72. {circup-1.8.0 → circup-1.9.0}/tests/test_bundle_config.json +0 -0
  73. {circup-1.8.0 → circup-1.9.0}/tests/test_bundle_config.json.license +0 -0
  74. {circup-1.8.0 → circup-1.9.0}/tests/test_bundle_config_local.json +0 -0
  75. {circup-1.8.0 → circup-1.9.0}/tests/test_bundle_config_local.json.license +0 -0
  76. {circup-1.8.0 → circup-1.9.0}/tests/test_circup.py +0 -0
  77. {circup-1.8.0 → circup-1.9.0}/tests/test_module.mpy +0 -0
  78. {circup-1.8.0 → circup-1.9.0}/tests/test_module.mpy.license +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: circup
3
- Version: 1.8.0
3
+ Version: 1.9.0
4
4
  Summary: A tool to manage/update libraries on CircuitPython devices.
5
5
  Home-page: https://github.com/adafruit/circup
6
6
  Author: Adafruit Industries
@@ -57,16 +57,16 @@ Requires-Dist: sphinx; extra == "dev"
57
57
  Requires-Dist: wheel; extra == "dev"
58
58
  Requires-Dist: twine; extra == "dev"
59
59
  Provides-Extra: all
60
+ Requires-Dist: pytest; extra == "all"
61
+ Requires-Dist: sphinx; extra == "all"
60
62
  Requires-Dist: wheel; extra == "all"
63
+ Requires-Dist: pytest-random-order>=1.0.0; extra == "all"
61
64
  Requires-Dist: pytest-faulthandler; extra == "all"
62
65
  Requires-Dist: coverage; extra == "all"
63
66
  Requires-Dist: pylint; extra == "all"
64
- Requires-Dist: pytest; extra == "all"
65
67
  Requires-Dist: twine; extra == "all"
66
- Requires-Dist: sphinx; extra == "all"
67
- Requires-Dist: black; extra == "all"
68
- Requires-Dist: pytest-random-order>=1.0.0; extra == "all"
69
68
  Requires-Dist: pytest-cov; extra == "all"
69
+ Requires-Dist: black; extra == "all"
70
70
 
71
71
 
72
72
  CircUp
@@ -90,7 +90,13 @@ class Backend:
90
90
  """
91
91
  raise NotImplementedError
92
92
 
93
- # pylint: disable=too-many-locals,too-many-branches,too-many-arguments,too-many-nested-blocks
93
+ def copy_file(self, target_file, location_to_paste):
94
+ """Paste a copy of the specified file at the location given
95
+ To be overridden by subclass
96
+ """
97
+ raise NotImplementedError
98
+
99
+ # pylint: disable=too-many-locals,too-many-branches,too-many-arguments,too-many-nested-blocks,too-many-statements
94
100
  def install_module(
95
101
  self, device_path, device_modules, name, pyext, mod_names, upgrade=False
96
102
  ): # pragma: no cover
@@ -109,9 +115,19 @@ class Backend:
109
115
  with get_bundle_versions()
110
116
  :param bool upgrade: Upgrade the specified modules if they're already installed.
111
117
  """
118
+ local_path = None
119
+ if os.path.exists(name):
120
+ # local file exists use that.
121
+ local_path = name
122
+ name = local_path.split(os.path.sep)[-1]
123
+ name = name.replace(".py", "").replace(".mpy", "")
124
+ click.echo(f"Installing from local path: {local_path}")
125
+
112
126
  if not name:
113
127
  click.echo("No module name(s) provided.")
114
- elif name in mod_names:
128
+ return
129
+ if name in mod_names or local_path is not None:
130
+
115
131
  # Grab device modules to check if module already installed
116
132
  if name in device_modules:
117
133
  if not upgrade:
@@ -129,14 +145,19 @@ class Backend:
129
145
  module_path = _metadata["path"]
130
146
  self.uninstall(device_path, module_path)
131
147
 
148
+ new_module_size = 0
132
149
  library_path = (
133
150
  os.path.join(device_path, self.LIB_DIR_PATH)
134
151
  if not isinstance(self, WebBackend)
135
152
  else urljoin(device_path, self.LIB_DIR_PATH)
136
153
  )
137
- metadata = mod_names[name]
138
- bundle = metadata["bundle"]
139
- bundle.size = os.path.getsize(metadata["path"])
154
+ if local_path is None:
155
+ metadata = mod_names[name]
156
+ bundle = metadata["bundle"]
157
+ else:
158
+ metadata = {"path": local_path}
159
+
160
+ new_module_size = os.path.getsize(metadata["path"])
140
161
  if os.path.isdir(metadata["path"]):
141
162
  # pylint: disable=unused-variable
142
163
  for dirpath, dirnames, filenames in os.walk(metadata["path"]):
@@ -144,7 +165,7 @@ class Backend:
144
165
  fp = os.path.join(dirpath, f)
145
166
  try:
146
167
  if not os.path.islink(fp): # Ignore symbolic links
147
- bundle.size += os.path.getsize(fp)
168
+ new_module_size += os.path.getsize(fp)
148
169
  else:
149
170
  self.logger.warning(
150
171
  f"Skipping symbolic link in space calculation: {fp}"
@@ -154,27 +175,29 @@ class Backend:
154
175
  f"Error: {e} - Skipping file in space calculation: {fp}"
155
176
  )
156
177
 
157
- if self.get_free_space() < bundle.size:
178
+ if self.get_free_space() < new_module_size:
158
179
  self.logger.error(
159
180
  f"Aborted installing module {name} - "
160
- f"not enough free space ({bundle.size} < {self.get_free_space()})"
181
+ f"not enough free space ({new_module_size} < {self.get_free_space()})"
161
182
  )
162
183
  click.secho(
163
184
  f"Aborted installing module {name} - "
164
- f"not enough free space ({bundle.size} < {self.get_free_space()})",
185
+ f"not enough free space ({new_module_size} < {self.get_free_space()})",
165
186
  fg="red",
166
187
  )
167
188
  return
168
189
 
169
190
  # Create the library directory first.
170
191
  self._create_library_directory(device_path, library_path)
171
-
172
- if pyext:
173
- # Use Python source for module.
174
- self.install_module_py(metadata)
192
+ if local_path is None:
193
+ if pyext:
194
+ # Use Python source for module.
195
+ self.install_module_py(metadata)
196
+ else:
197
+ # Use pre-compiled mpy modules.
198
+ self.install_module_mpy(bundle, metadata)
175
199
  else:
176
- # Use pre-compiled mpy modules.
177
- self.install_module_mpy(bundle, metadata)
200
+ self.copy_file(metadata["path"], "lib")
178
201
  click.echo("Installed '{}'.".format(name))
179
202
  else:
180
203
  click.echo("Unknown module named, '{}'.".format(name))
@@ -520,6 +543,17 @@ class WebBackend(Backend):
520
543
  _writeable_error()
521
544
  r.raise_for_status()
522
545
 
546
+ def copy_file(self, target_file, location_to_paste):
547
+ if os.path.isdir(target_file):
548
+ create_directory_url = urljoin(
549
+ self.device_location,
550
+ "/".join(("fs", location_to_paste, target_file, "")),
551
+ )
552
+ self._create_library_directory(self.device_location, create_directory_url)
553
+ self.install_dir_http(target_file)
554
+ else:
555
+ self.install_file_http(target_file)
556
+
523
557
  def install_module_mpy(self, bundle, metadata):
524
558
  """
525
559
  :param bundle library bundle.
@@ -775,6 +809,19 @@ class DiskBackend(Backend):
775
809
  if not os.path.exists(library_path): # pragma: no cover
776
810
  os.makedirs(library_path)
777
811
 
812
+ def copy_file(self, target_file, location_to_paste):
813
+ target_filename = target_file.split(os.path.sep)[-1]
814
+ if os.path.isdir(target_file):
815
+ shutil.copytree(
816
+ target_file,
817
+ os.path.join(self.device_location, location_to_paste, target_filename),
818
+ )
819
+ else:
820
+ shutil.copyfile(
821
+ target_file,
822
+ os.path.join(self.device_location, location_to_paste, target_filename),
823
+ )
824
+
778
825
  def install_module_mpy(self, bundle, metadata):
779
826
  """
780
827
  :param bundle library bundle.
@@ -6,6 +6,7 @@ Functions called from commands in order to provide behaviors and return informat
6
6
  """
7
7
 
8
8
  import ctypes
9
+ import glob
9
10
  import os
10
11
 
11
12
  from subprocess import check_output
@@ -90,6 +91,7 @@ def completion_for_install(ctx, param, incomplete):
90
91
  module_names = {m.replace(".py", "") for m in available_modules}
91
92
  if incomplete:
92
93
  module_names = [name for name in module_names if name.startswith(incomplete)]
94
+ module_names.extend(glob.glob(f"{incomplete}*"))
93
95
  return sorted(module_names)
94
96
 
95
97
 
@@ -446,6 +448,7 @@ def get_dependencies(*requested_libraries, mod_names, to_install=()):
446
448
  :param list(str) to_install: Modules already selected for installation.
447
449
  :return: tuple of module names to install which we build
448
450
  """
451
+ # pylint: disable=too-many-branches
449
452
  # Internal variables
450
453
  _to_install = to_install
451
454
  _requested_libraries = []
@@ -471,10 +474,14 @@ def get_dependencies(*requested_libraries, mod_names, to_install=()):
471
474
  _requested_libraries.append(canonical_lib_name)
472
475
  except KeyError:
473
476
  if canonical_lib_name not in WARNING_IGNORE_MODULES:
474
- click.secho(
475
- f"WARNING:\n\t{canonical_lib_name} is not a known CircuitPython library.",
476
- fg="yellow",
477
- )
477
+ if os.path.exists(canonical_lib_name):
478
+ _requested_libraries.append(canonical_lib_name)
479
+ else:
480
+ click.secho(
481
+ f"WARNING:\n\t{canonical_lib_name} "
482
+ f"is not a known CircuitPython library.",
483
+ fg="yellow",
484
+ )
478
485
 
479
486
  if not _requested_libraries:
480
487
  # If nothing is requested, we're done
@@ -484,16 +491,20 @@ def get_dependencies(*requested_libraries, mod_names, to_install=()):
484
491
  if library not in _to_install:
485
492
  _to_install = _to_install + (library,)
486
493
  # get the requirements.txt from bundle
487
- bundle = mod_names[library]["bundle"]
488
- requirements_txt = bundle.requirements_for(library)
489
- if requirements_txt:
490
- _requested_libraries.extend(
491
- libraries_from_requirements(requirements_txt)
492
- )
494
+ try:
495
+ bundle = mod_names[library]["bundle"]
496
+ requirements_txt = bundle.requirements_for(library)
497
+ if requirements_txt:
498
+ _requested_libraries.extend(
499
+ libraries_from_requirements(requirements_txt)
500
+ )
493
501
 
494
- circup_dependencies = get_circup_dependencies(bundle, library)
495
- for circup_dependency in circup_dependencies:
496
- _requested_libraries.append(circup_dependency)
502
+ circup_dependencies = get_circup_dependencies(bundle, library)
503
+ for circup_dependency in circup_dependencies:
504
+ _requested_libraries.append(circup_dependency)
505
+ except KeyError:
506
+ # don't check local file for further dependencies
507
+ pass
497
508
 
498
509
  # we've processed this library, remove it from the list
499
510
  _requested_libraries.remove(library)
@@ -302,7 +302,7 @@ def install(
302
302
  """
303
303
  Install a named module(s) onto the device. Multiple modules
304
304
  can be installed at once by providing more than one module name, each
305
- separated by a space.
305
+ separated by a space. Modules can be from a Bundle or local filepaths.
306
306
  """
307
307
 
308
308
  # TODO: Ensure there's enough space on the device
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: circup
3
- Version: 1.8.0
3
+ Version: 1.9.0
4
4
  Summary: A tool to manage/update libraries on CircuitPython devices.
5
5
  Home-page: https://github.com/adafruit/circup
6
6
  Author: Adafruit Industries
@@ -57,16 +57,16 @@ Requires-Dist: sphinx; extra == "dev"
57
57
  Requires-Dist: wheel; extra == "dev"
58
58
  Requires-Dist: twine; extra == "dev"
59
59
  Provides-Extra: all
60
+ Requires-Dist: pytest; extra == "all"
61
+ Requires-Dist: sphinx; extra == "all"
60
62
  Requires-Dist: wheel; extra == "all"
63
+ Requires-Dist: pytest-random-order>=1.0.0; extra == "all"
61
64
  Requires-Dist: pytest-faulthandler; extra == "all"
62
65
  Requires-Dist: coverage; extra == "all"
63
66
  Requires-Dist: pylint; extra == "all"
64
- Requires-Dist: pytest; extra == "all"
65
67
  Requires-Dist: twine; extra == "all"
66
- Requires-Dist: sphinx; extra == "all"
67
- Requires-Dist: black; extra == "all"
68
- Requires-Dist: pytest-random-order>=1.0.0; extra == "all"
69
68
  Requires-Dist: pytest-cov; extra == "all"
69
+ Requires-Dist: black; extra == "all"
70
70
 
71
71
 
72
72
  CircUp
@@ -4,5 +4,5 @@
4
4
  # pylint: disable=all
5
5
  import adafruit_bus_device
6
6
  from adafruit_button import Button
7
- import adafruit_esp32spi.adafruit_esp32spi_socket as socket
7
+ from adafruit_esp32spi import adafruit_esp32spi_socketpool
8
8
  import adafruit_hid.consumer_control
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -10,16 +10,16 @@ update_checker
10
10
  importlib_metadata
11
11
 
12
12
  [all]
13
+ pytest
14
+ sphinx
13
15
  wheel
16
+ pytest-random-order>=1.0.0
14
17
  pytest-faulthandler
15
18
  coverage
16
19
  pylint
17
- pytest
18
20
  twine
19
- sphinx
20
- black
21
- pytest-random-order>=1.0.0
22
21
  pytest-cov
22
+ black
23
23
 
24
24
  [dev]
25
25
  pytest
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes