mcmu 1.4.0.dev0__tar.gz → 2.0.0.dev1__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.
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## **2.0.0.dev1** - 2026-03-17
4
+
5
+ ### Changed
6
+
7
+ * Changed the name of the file when downloading
8
+
9
+ ### Removed
10
+
11
+ * Removed the need for the config file
12
+
13
+ ### Fixed
14
+
15
+ * Fixed displaying mod name when upgrading
16
+
3
17
  ## [1.4.0.dev0] - 2026-03-16
4
18
 
5
19
  ### Added
@@ -237,27 +251,3 @@ This is the first release candidate for version [1.0.0+1.21.11].
237
251
  ## [0.1.0] - 2026-03-03
238
252
 
239
253
  - Initial Release
240
-
241
- [0.1.0]: https://github.com/Josiah-Jarvis/MCModUpdater/releases/tag/0.1.0
242
- [0.1.1]: https://github.com/Josiah-Jarvis/MCModUpdater/releases/tag/0.1.1
243
- [0.1.2]: https://github.com/Josiah-Jarvis/MCModUpdater/releases/tag/0.1.2
244
- [0.1.3]: https://github.com/Josiah-Jarvis/MCModUpdater/releases/tag/0.1.3
245
- [0.1.4]: https://github.com/Josiah-Jarvis/MCModUpdater/releases/tag/0.1.4
246
- [0.2.0]: https://github.com/Josiah-Jarvis/MCModUpdater/releases/tag/0.2.0
247
- [0.2.1]: https://github.com/Josiah-Jarvis/MCModUpdater/releases/tag/0.2.1
248
- [0.2.2]: https://github.com/Josiah-Jarvis/MCModUpdater/releases/tag/0.2.2
249
- [1.0.0rc0]: https://github.com/Josiah-Jarvis/MCModUpdater/releases/tag/1.0.0rc0
250
- [1.0.0rc1]: https://github.com/Josiah-Jarvis/MCModUpdater/releases/tag/1.0.0rc1
251
- [1.0.0]: https://github.com/Josiah-Jarvis/MCModUpdater/releases/tag/1.0.0
252
- [1.1.0.dev0]: https://github.com/Josiah-Jarvis/MCModUpdater/releases/tag/1.1.0.dev0
253
- [1.1.0.dev1]: https://github.com/Josiah-Jarvis/MCModUpdater/releases/tag/1.1.0.dev1
254
- [1.1.0]: https://github.com/Josiah-Jarvis/MCModUpdater/releases/tag/1.1.0
255
- [1.1.1a0]: https://github.com/Josiah-Jarvis/MCModUpdater/releases/tag/1.1.1a0
256
- [1.1.1]: https://github.com/Josiah-Jarvis/MCModUpdater/releases/tag/1.1.1
257
- [1.2.0.dev0]: https://github.com/Josiah-Jarvis/MCModUpdater/releases/tag/1.2.0.dev0
258
- [1.2.0.dev1]: https://github.com/Josiah-Jarvis/MCModUpdater/releases/tag/1.2.0.dev1
259
- [1.2.0a0]: https://github.com/Josiah-Jarvis/MCModUpdater/releases/tag/1.2.0a0
260
- [1.2.0a1]: https://github.com/Josiah-Jarvis/MCModUpdater/releases/tag/1.2.0a1
261
- [1.2.0rc0]: https://github.com/Josiah-Jarvis/MCModUpdater/releases/tag/1.2.0rc0
262
- [1.2.0]: https://github.com/Josiah-Jarvis/MCModUpdater/releases/tag/1.2.0
263
- [1.2.1]: https://github.com/Josiah-Jarvis/MCModUpdater/releases/tag/1.2.1
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcmu
3
- Version: 1.4.0.dev0
3
+ Version: 2.0.0.dev1
4
4
  Summary: A utility to update Minecraft java edition mods from Modrinth
5
5
  Project-URL: homepage, https://github.com/Josiah-Jarvis/MCMU
6
6
  Project-URL: source, https://github.com/Josiah-Jarvis/MCMU/
7
7
  Project-URL: download, https://pypi.org/project/mcmu/#files
8
8
  Project-URL: changelog, https://github.com/Josiah-Jarvis/MCMU/blob/master/CHANGELOG.md
9
- Project-URL: releasenotes, https://github.com/Josiah-Jarvis/MCMU/compare/v1.3.0...v1.4.0.dev0
9
+ Project-URL: releasenotes, https://github.com/Josiah-Jarvis/MCMU/compare/v1.4.0.dev0...v2.0.0.dev1
10
10
  Project-URL: documentation, https://github.com/Josiah-Jarvis/MCMU/blob/master/README.md
11
11
  Project-URL: issues, https://github.com/Josiah-Jarvis/MCMU/issues
12
12
  Author: Josiah Jarvis
@@ -25,7 +25,6 @@ Classifier: Natural Language :: English
25
25
  Classifier: Operating System :: MacOS
26
26
  Classifier: Operating System :: Microsoft
27
27
  Classifier: Operating System :: Microsoft :: Windows
28
- Classifier: Operating System :: Microsoft :: Windows :: Windows 10
29
28
  Classifier: Operating System :: Microsoft :: Windows :: Windows 11
30
29
  Classifier: Operating System :: POSIX
31
30
  Classifier: Operating System :: POSIX :: Linux
@@ -126,3 +125,7 @@ mcmu -g game_version -i mod-name
126
125
  ### How does it work?
127
126
 
128
127
  It works a lot like a package manager actually! It pulls the mods from a source (Modrinth) and installs them on the system. It keeps a list of the installed mods in a config file for easy access of the installed mods.
128
+
129
+ ### What happened to v1.4.0?
130
+
131
+ It turned into v2.0.0.
@@ -82,3 +82,7 @@ mcmu -g game_version -i mod-name
82
82
  ### How does it work?
83
83
 
84
84
  It works a lot like a package manager actually! It pulls the mods from a source (Modrinth) and installs them on the system. It keeps a list of the installed mods in a config file for easy access of the installed mods.
85
+
86
+ ### What happened to v1.4.0?
87
+
88
+ It turned into v2.0.0.
@@ -2,11 +2,10 @@
2
2
 
3
3
  ## To Do
4
4
 
5
- [ ] Get rid of the config file (might have found a solution!)
6
-
7
5
  ## In Progress
8
6
 
9
7
  [ ] Install mod dependencies
8
+ [ ] Get rid of the config file (might have found a solution!)
10
9
 
11
10
  ## Completed
12
11
 
@@ -28,7 +28,6 @@ classifiers = [
28
28
  "Operating System :: MacOS",
29
29
  "Operating System :: Microsoft",
30
30
  "Operating System :: Microsoft :: Windows",
31
- "Operating System :: Microsoft :: Windows :: Windows 10",
32
31
  "Operating System :: Microsoft :: Windows :: Windows 11",
33
32
  "Operating System :: POSIX",
34
33
  "Operating System :: POSIX :: Linux",
@@ -52,7 +51,7 @@ homepage = "https://github.com/Josiah-Jarvis/MCMU"
52
51
  source = "https://github.com/Josiah-Jarvis/MCMU/"
53
52
  download = "https://pypi.org/project/mcmu/#files"
54
53
  changelog = "https://github.com/Josiah-Jarvis/MCMU/blob/master/CHANGELOG.md"
55
- releasenotes = "https://github.com/Josiah-Jarvis/MCMU/compare/v1.3.0...v1.4.0.dev0" # Change before every release
54
+ releasenotes = "https://github.com/Josiah-Jarvis/MCMU/compare/v1.4.0.dev0...v2.0.0.dev1" # Change before every release
56
55
  documentation = "https://github.com/Josiah-Jarvis/MCMU/blob/master/README.md"
57
56
  issues = "https://github.com/Josiah-Jarvis/MCMU/issues"
58
57
 
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+
4
+ from re import match
5
+ from os import listdir
6
+ from pathlib import Path
7
+
8
+
9
+ class Mod:
10
+ def __init__(self, mod_path: Path):
11
+ self.mod_path = mod_path
12
+
13
+ def list_mods(self):
14
+ mods = {}
15
+ for mod in listdir(self.mod_path):
16
+ pattern = r'^(.*?)_version_(.*)\.jar$'
17
+ m = match(pattern, mod)
18
+ mods[m.group(1)] = {
19
+ "name": m.group(1),
20
+ "version": m.group(2),
21
+ "file": mod
22
+ }
23
+
24
+ return mods
@@ -6,6 +6,7 @@
6
6
 
7
7
  from requests import get
8
8
 
9
+
9
10
  class ModrinthAPI:
10
11
  def __init__(self, UserAgent: str):
11
12
  self.headers = {
@@ -95,5 +96,3 @@ class ModrinthAPI:
95
96
  return response.status_code
96
97
  else:
97
98
  return response.json()
98
-
99
-
@@ -0,0 +1,9 @@
1
+ # Breaking changes between v1.3.0 and v2.0.0
2
+
3
+ This update breaks everything!
4
+
5
+ Why does it break everything? Because we are dropping the config file! Now the config is stored in the mods file name, now it is stored as {mod_name}_version_{mod_version}.jar.
6
+
7
+ ## How to update safely
8
+
9
+ In v1.3.0 of MCMU do `mcmu -l` to get a list of all your mods. Keep this safe. One by one delete all your mods with `mcmu -r <modname>` then update MCMU with `pip install --upgrade mcmu`. Next reinstall all your mods with `mcmu -i <modname>`.
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env python3
2
2
  # -*- coding: utf-8 -*-
3
3
 
4
- from copy import copy # Import copy
5
- from json import load, dump, JSONDecodeError # Import JSON functions
4
+ import sys
6
5
  from pathlib import Path # Import for file functions
7
6
  from logging import getLogger, basicConfig # Logging functionality
8
7
  from requests import get # Get files from the CDN
9
8
  from argparse import ArgumentParser # Command line arguments class
10
9
  from .ModrinthAPI import ModrinthAPI # Modrinth API code (Local import)
10
+ from .Mod import Mod
11
11
 
12
- __version__ = "1.4.0.dev0"
12
+ __version__ = "2.0.0.dev1"
13
13
  __author__ = "Josiah Jarvis"
14
14
 
15
15
  logger = getLogger(__name__)
@@ -33,6 +33,7 @@ config_file = Path(args.minecraft_dir, "config/mcmu.json") # Path to the config
33
33
 
34
34
  ModAPI = ModrinthAPI(f"Josiah-Jarvis/MCMU/{__version__} (https://github.com/Josiah-Jarvis/MCMU)")
35
35
 
36
+
36
37
  def check_update(mod_name: str, current_version: str) -> [bool, dict]:
37
38
  """Checks for mod update from Modrinth
38
39
 
@@ -61,24 +62,6 @@ def check_update(mod_name: str, current_version: str) -> [bool, dict]:
61
62
  return latest_version
62
63
  return False # Return false for failure
63
64
 
64
- def write_config_file(config_f: Path, config_d: dict):
65
- """Writes the config file
66
-
67
- Arguments:
68
- config_f -- The config file
69
- config_d -- The config data
70
-
71
- Returns:
72
- True: Success
73
- False: Failure
74
- """
75
- try:
76
- with open(config_f, "w") as fp: # Open the config file
77
- dump(config_d, fp, indent=4) # Write the config file
78
- return True
79
- except PermissionError: # Uh oh we do not have permission
80
- logger.error("No permission to write to file.")
81
- return False
82
65
 
83
66
  def main():
84
67
  """Main function
@@ -87,23 +70,8 @@ def main():
87
70
  1: Failure
88
71
  0: Success
89
72
  """
90
- try:
91
- with open(config_file, "r") as fp: # Open the config file
92
- config = load(fp) # Read the config file
93
- except JSONDecodeError:
94
- logger.critical("Config file not valid JSON.") # Well its not valid JSON
95
- return 1
96
- except FileNotFoundError: # Oops config file does not exist
97
- logger.warn("Config file does not exist.")
98
- with open(config_file, "w") as fp: # Create the file since it does not exist
99
- logger.debug("Creating config file.")
100
- dump({"mods":{}}, fp, indent=4)
101
- config = {"mods":{}}
102
- except PermissionError: # Can't we just have the permission :?
103
- logger.error("No permission to write to file.")
104
- return 1
105
- mods = copy(config['mods']) # Get the mods data from the config file
106
73
  mod_path = Path(args.minecraft_dir, "mods/") # Path to folder where the mod jar's are stored
74
+ mods = Mod(mod_path).list_mods()
107
75
  if not mod_path.exists():
108
76
  logger.critical(f"Mods folder: {mod_path} does not exist. Please create it.\nExiting...") # Fabric creates the mods/ folder on first run by they might not have run it yet
109
77
  return 1
@@ -119,27 +87,24 @@ def main():
119
87
  elif latest_version: # If latest version is a dict it should return True
120
88
  old_file = Path(mod_path, mods[mod_name]['file']) # Path to the old mod file
121
89
  additional_storage = latest_version['files'][0]['size'] - old_file.stat().st_size # Calculate how much more storage will be taken up
122
- if input(f"{args.install} will take up: {additional_storage} additional bytes, would you like to install? [Y/n]: ") is ("" or "Y"): # Ask them if they want to install it
90
+ if input(f"{mods[mod_name]['name']} will take up: {additional_storage} additional bytes, would you like to install? [Y/n]: ") is ("" or "Y"): # Ask them if they want to install it
123
91
  old_file.unlink() # Delete old file
124
92
  response = get(latest_version['files'][0]['url'], stream=True) # Get the new file
125
93
  if response.status_code != 200: # If its not 200 fail
126
94
  print(f"Failed to download the mod. Status code: {response.status_code}")
127
95
  return 1
128
- with open(f"{mod_path}/{latest_version['files'][0]['filename']}", 'wb') as file: # IF everything good write to the file
96
+ with open(f"{mod_path}/{args.install}_version_{latest_version['version_number']}.jar", 'wb') as file: # IF everything good write to the file
129
97
  for chunk in response.iter_content(chunk_size=1024):
130
98
  if chunk:
131
99
  file.write(chunk)
132
- print(f"Downloaded {latest_version['files'][0]['filename']} successfully.") # Print the success
133
- config['mods'][mod_name] = {'file': latest_version['files'][0]['filename'], 'version': latest_version['version_number'], 'name': mod_name}
134
- if not write_config_file(config_file, config): # Write the config file
135
- return 1 # Fail if writing failed
100
+ print(f"Downloaded mod at {mod_path}/{args.install}_version_{latest_version['version_number']}.jar successfully.") # Print the success
136
101
  else:
137
102
  print("Canceling.")
138
103
  return 0
139
104
  else:
140
105
  print(f"Mod: {mod_name} at latest version!")
141
106
  elif args.install: # If were installing the mod
142
- if args.install in config['mods']: # If mod already installed exit
107
+ if args.install in mods: # If mod already installed exit
143
108
  print(f"{args.install} already installed.")
144
109
  return 0
145
110
  latest_version = check_update(args.install, "0") # Set the version to 0 so any version would be higher
@@ -152,14 +117,11 @@ def main():
152
117
  if response.status_code != 200:
153
118
  print(f"Failed to download the mod. Status code: {response.status_code}")
154
119
  return False
155
- with open(f"{mod_path}/{latest_version['files'][0]['filename']}", 'wb') as file: # Write to the jar file
120
+ with open(f"{mod_path}/{args.install}_version_{latest_version['version_number']}.jar", 'wb') as file: # Write to the jar file
156
121
  for chunk in response.iter_content(chunk_size=1024):
157
122
  if chunk:
158
123
  file.write(chunk)
159
- print(f"Downloaded {latest_version['files'][0]['filename']} successfully.") # Print the success
160
- config['mods'][args.install] = {'file': latest_version['files'][0]['filename'], 'version': latest_version['version_number'], 'name': args.install}
161
- if not write_config_file(config_file, config): # Write to the config file
162
- return 1
124
+ print(f"Downloaded mod at {mod_path}/{args.install}_version_{latest_version['version_number']}.jar successfully.") # Print the success
163
125
  else:
164
126
  print("Canceling.")
165
127
  return 0
@@ -167,11 +129,11 @@ def main():
167
129
  logger.error("Mod does not exist on Modrinth")
168
130
  return 1
169
131
  elif args.remove: # If were removing the mod
170
- if args.remove not in config['mods']: # If the mod is not listed in the config file exit with error
132
+ if args.remove not in mods: # If the mod is not listed in the config file exit with error
171
133
  logger.error("Mod not installed")
172
134
  return 1
173
135
  try:
174
- mod_file = Path(mod_path, config['mods'][args.remove]['file']) # Path to the mod jar
136
+ mod_file = Path(mod_path, mods[args.remove]['file']) # Path to the mod jar
175
137
  if input(f"Would you like to remove {args.remove}? This operation will clear {mod_file.stat().st_size} bytes. [Y/n]: ") is ("" or "Y"): # Ask if they want to remove it
176
138
  mod_file.unlink() # Remove the file
177
139
  else:
@@ -182,24 +144,21 @@ def main():
182
144
  except PermissionError: # No permission to delete the file
183
145
  logger.critical("No permission to delete mod file.")
184
146
  return 1
185
- del config['mods'][args.remove] # Remove the mods entry in the config file
186
- if not write_config_file(config_file, config): # Write to the config file
187
- return 1
188
147
  print(f"Mod: {args.remove}, successfully removed") # Print success
189
148
  return 0
190
149
  elif args.list: # List installed mod
191
- for mod in config['mods']: # Iterate over all installed mods
192
- print(f"{config['mods'][mod]['name']}\n\tVersion: {config['mods'][mod]['version']}\n\tFile: {config['mods'][mod]['file']}")
150
+ for mod in mods: # Iterate over all installed mods
151
+ print(f"{mods[mod]['name']}\n\tVersion: {mods[mod]['version']}\n\tFile: {mods[mod]['file']}")
193
152
  elif args.search: # If we are searching for a mod
194
153
  response = ModAPI.search(args.search, '[["categories:fabric"],["project_type:mod"]]')
195
154
  if response == 410: # That means the API is deprecated: https://docs.modrinth.com/api/
196
155
  logger.critical("API is deprecated, you probably have to update MCMU")
197
156
  elif response == 400: # Response of 400 means request was invalid: https://docs.modrinth.com/api/operations/searchprojects/
198
- logger.error(f"Request invalid") # Print error
157
+ logger.error("Request invalid") # Print error
199
158
  else:
200
159
  for mod in response['hits']: # Iterate over and list all the mods
201
160
  print(f"{mod['title']}:\n\tDescription: {mod['description']}\n\tAuthor: {mod['author']}\n\tDownloads: {mod['downloads']}\n\tLatest Version: {mod['latest_version']}\n\n")
202
161
  else:
203
162
  parser.print_help() # Prints help message if there is nothing to do
204
163
 
205
- return 0 # Return 0 if all good
164
+ return 0 # Return 0 if all good
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes