Skip to content

Commit

Permalink
Added downloading packages from remote index
Browse files Browse the repository at this point in the history
  • Loading branch information
PJ-Finlay committed Feb 6, 2021
1 parent a2e0602 commit 8ae1c39
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 20 deletions.
108 changes: 88 additions & 20 deletions argostranslate/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,39 @@
import json
import shutil

import requests

from argostranslate import settings

class Package:
"""An installed package.
"""
## `package` module example usage
```
from argostranslate import package
# Update package definitions from remote
package.update_package_index()
# Load available packages from local package index
available_packages = package.load_available_packages()
# Download and install all available packages
for available_package in available_packages:
download_path = available_package.download()
package.install_from_path(download_path)
"""

class IPackage:
"""A package, can be either installed locally or available from a remote package index.
Attributes:
package_path (Path): The path to the installed package.
package_path (Path): The path to the installed package. None if not installed.
package_version (str): The version of the package.
argos_version (str): The version of Argos Translate the package is intended for.
from_code (str): The code of the language the package translates from.
from_name (str): Human readable name of the language the package translates from.
to_code (str): The code of the language the package translates to.
to_name (str): Human readable name of the language the package translates to.
links [list(str)]: A list of links to download the package
Packages are a zip archive of a directory with metadata.json
in its root the .argosmodel file extension. By default a
Expand All @@ -34,31 +54,26 @@ class Package:
"from_code": "en",
"from_name": "English",
"to_code": "es",
"to_name": "Spanish"
"to_name": "Spanish",
"links": ["https://example.com/en_es.argosmodel"]
}
"""

def __init__(self, package_path):
"""Create a new Package.
def load_metadata_from_json(self, metadata):
"""Loads package metadata from a JSON object.
Args:
package_path (str): Path to installed package directory.
metadata: A json object from json.load
"""
self.package_path = package_path
metadata_path = package_path / 'metadata.json'
if not metadata_path.exists():
raise Exception('Error opening package at ' +
str(metadata_path) + ' no metadata.json')
with open(metadata_path) as metadata_file:
metadata = json.load(metadata_file)
self.package_version = metadata.get('package_version')
self.argos_version = metadata.get('argos_version')
self.from_code = metadata.get('from_code')
self.from_name = metadata.get('from_name')
self.to_code = metadata.get('to_code')
self.to_name = metadata.get('to_name')
self.package_version = metadata.get('package_version')
self.argos_version = metadata.get('argos_version')
self.from_code = metadata.get('from_code')
self.from_name = metadata.get('from_name')
self.to_code = metadata.get('to_code')
self.to_name = metadata.get('to_name')
self.links = metadata.get('links')

def get_readme(self):
"""Returns the text of the README.md in this package.
Expand All @@ -78,6 +93,40 @@ def get_readme(self):
def __str__(self):
return "{} -> {}".format(self.from_name, self.to_name)

class Package(IPackage):
"""An installed package"""
def __init__(self, package_path):
"""Create a new Package from path.
Args:
package_path (str): Path to installed package directory.
"""
self.package_path = package_path
metadata_path = package_path / 'metadata.json'
if not metadata_path.exists():
raise Exception('Error opening package at ' +
str(metadata_path) + ' no metadata.json')
with open(metadata_path) as metadata_file:
metadata = json.load(metadata_file)
self.load_metadata_from_json(metadata)

class AvailablePackage(IPackage):
"""A package available for download"""
def __init__(self, metadata):
"""Creates a new AvailablePackage from a metadata object"""
self.load_metadata_from_json(metadata)

def download(self):
"""Downloads the AvailablePackage and returns its path"""
url = self.links[0]
filename = self.from_code + '_' + self.to_code + '.argosmodel'
filepath = settings.downloads_dir / filename
r = requests.get(url, allow_redirects=True)
open(filepath, 'wb').write(r.content)
return filepath


def install_from_path(path):
"""Install a package (zip archive ending in .argosmodel).
Expand Down Expand Up @@ -120,3 +169,22 @@ def get_installed_packages(path=None):
to_return.append(Package(path))
return to_return

def update_package_index():
"""Downloads remote package index"""
r = requests.get(settings.remote_package_index, allow_redirects=True)
open(settings.local_package_index, 'wb').write(r.content)

def load_available_packages():
"""Returns a list of AvailablePackages from the package index."""
try:
with open(settings.local_package_index) as index_file:
index = json.load(index_file)
to_return = []
for metadata in index:
package = AvailablePackage(metadata)
to_return.append(package)
return to_return
except FileNotFoundError:
raise Exception('Local package index not found,' +
' use package.update_package_index() to load it')

7 changes: 7 additions & 0 deletions argostranslate/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
default=home_dir / '.local' / 'cache')) / 'argos-translate'
os.makedirs(cache_dir, exist_ok=True)

downloads_dir = cache_dir / 'downloads'
os.makedirs(downloads_dir, exist_ok=True)

# Legacy support to upgrade from argostranslate<1.1.0
legacy_package_data_dirs = [Path.home() / '.argos-translate' / 'packages']
if 'SNAP' in os.environ:
Expand Down Expand Up @@ -49,6 +52,10 @@
package_dirs.append(Path(os.environ[
'ARGOS_TRANSLATE_PACKAGE_DIR']))

remote_package_index = 'https://raw.githubusercontent.com/argosopentech/argospm-index/main/index.json'

This comment has been minimized.

Copy link
@pierotofy

pierotofy Feb 7, 2021

Contributor

Love the idea of an index 👍


local_package_index = cache_dir / 'index.json'

about_text = """
Argos Translate is an open source neural machine
translation application created by Argos Open
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ ctranslate2==1.17.1
sentencepiece==0.1.91
stanza==1.1.1
PyQt5==5.15.1
requests==2.25.1
sphinx==3.2.1
sphinx-rtd-theme==0.5.0

0 comments on commit 8ae1c39

Please sign in to comment.