Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow to download multiple files and folders #16

Merged
merged 11 commits into from
Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .annotation_safe_list.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# This is a Code Annotations automatically-generated Django model safelist file.
# These models must be annotated as follows in order to be counted in the coverage report.
# See https://code-annotations.readthedocs.io/en/latest/safelist.html for more information.
#
# fake_app_1.FakeModelName:
# ".. no_pii:": "This model has no PII"
# fake_app_2.FakeModel2:
# ".. choice_annotation:": foo, bar, baz

admin.LogEntry:
".. no_pii:": "This model has no PII"
auth.Group:
".. no_pii:": "This model has no PII"
auth.Permission:
".. no_pii:": "This model has no PII"
auth.User:
".. pii": "This model minimally contains a username, password, and email"
".. pii_types": "username, email_address, password"
".. pii_retirement": "consumer_api"
contenttypes.ContentType:
".. no_pii:": "This model has no PII"
sessions.Session:
".. no_pii:": "This model has no PII"
social_django.Association:
".. no_pii:": "This model has no PII"
social_django.Code:
".. pii:": "Email address"
".. pii_types:": other
".. pii_retirement:": local_api
social_django.Nonce:
".. no_pii:": "This model has no PII"
social_django.Partial:
".. no_pii:": "This model has no PII"
social_django.UserSocialAuth:
".. no_pii:": "This model has no PII"
waffle.Flag:
".. no_pii:": "This model has no PII"
waffle.Sample:
".. no_pii:": "This model has no PII"
waffle.Switch:
".. no_pii:": "This model has no PII"
13 changes: 8 additions & 5 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
[run]
branch = True
data_file = .coverage
source = filesmanager
source=filesmanager
omit =
tests
filesmanager/settings
filesmanager/locale/*
filesmanager/static
test_settings.py
*/migrations/*
*admin.py
*/static/*
*/templates/*
*/settings/*
*/locale/*
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ pip-log.txt
coverage.xml
htmlcov/


# Virtual environments
/venv/
/venv-*/
/.venv/
/.venv-*/

# The Silver Searcher
.agignore
Expand Down Expand Up @@ -71,3 +75,4 @@ requirements/private.txt
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pii_report/*
35 changes: 35 additions & 0 deletions .pii_annotations.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
source_path: ./
report_path: pii_report
safelist_path: .annotation_safe_list.yml
coverage_target: 80.0
annotations:
".. no_pii:":
"pii_group":
- ".. pii:":
- ".. pii_types:":
choices:
- id # Unique identifier for the user which is shared across systems
- name # Used for any part of the user's name
- username
- password
- location # Used for any part of any type address or country stored
- phone_number # Used for phone or fax numbers
- email_address
- birth_date # Used for any part of a stored birth date
- ip # IP address
- external_service # Used for external service ids or links such as social media links or usernames, website links, etc.
- biography # Any type of free-form biography field
- gender
- sex
- image
- video
- other
- ".. pii_retirement:":
choices:
- retained # Intentionally kept for legal reasons
- local_api # An API exists in this repository for retiring this information
- consumer_api # The data's consumer must implement an API for retiring this information
- third_party # A third party API exists to retire this data
extensions:
python:
- py
126 changes: 68 additions & 58 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,42 +1,36 @@
.DEFAULT_GOAL := help

.PHONY: dev.clean dev.build dev.run upgrade help requirements
.PHONY: extract_translations compile_translations
.PHONY: detect_changed_source_translations dummy_translations build_dummy_translations
.PHONY: validate_translations pull_translations push_translations symlink_translations install_transifex_clients

REPO_NAME := xblock-filesmanager
PACKAGE_NAME := filesmanager
EXTRACT_DIR := $(PACKAGE_NAME)/locale/en/LC_MESSAGES
EXTRACTED_DJANGO := $(EXTRACT_DIR)/django-partial.po
EXTRACTED_DJANGOJS := $(EXTRACT_DIR)/djangojs-partial.po
EXTRACTED_TEXT := $(EXTRACT_DIR)/text.po
JS_TARGET := public/js/translations
TRANSLATIONS_DIR := $(PACKAGE_NAME)/translations
.PHONY: clean clean_tox compile_translations coverage diff_cover docs dummy_translations \
extract_translations fake_translations help pii_check pull_translations push_translations \
quality requirements selfcheck test test-all upgrade validate install_transifex_client

help:
@perl -nle'print $& if m{^[\.a-zA-Z_-]+:.*?## .*$$}' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m %-25s\033[0m %s\n", $$1, $$2}'
.DEFAULT_GOAL := help

install-test:
pip install -qr requirements/test.txt
# For opening files in a browser. Use like: $(BROWSER)relative/path/to/file.html
BROWSER := python -m webbrowser file://$(CURDIR)/

install-dev:
pip install -qr requirements/dev.txt
help: ## display this help message
@echo "Please use \`make <target>' where <target> is one of"
@awk -F ':.*?## ' '/^[a-zA-Z]/ && NF==2 {printf "\033[36m %-25s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) | sort

install: install-test
clean: ## remove generated byte code, coverage reports, and build artifacts
find . -name '__pycache__' -exec rm -rf {} +
find . -name '*.pyc' -exec rm -f {} +
find . -name '*.pyo' -exec rm -f {} +
find . -name '*~' -exec rm -f {} +
coverage erase
rm -fr build/
rm -fr dist/
rm -fr *.egg-info

quality: ## Run the quality checks
pylint --rcfile=pylintrc filesmanager
python setup.py -q sdist
twine check dist/*
clean_tox: ## clear tox requirements cache
rm -fr .tox

test: ## Run the tests
mkdir -p var
rm -rf .coverage
python -m coverage run --rcfile=.coveragerc -m pytest
coverage: clean ## generate and view HTML coverage report
pytest --cov-report html
$(BROWSER)htmlcov/index.html

covreport: ## Show the coverage results
python -m coverage report -m --skip-covered
docs: ## generate Sphinx HTML documentation, including API docs
tox -e docs
$(BROWSER)docs/_build/html/index.html

# Define PIP_COMPILE_OPTS=-v to get more information during make upgrade.
PIP_COMPILE = pip-compile --upgrade $(PIP_COMPILE_OPTS)
Expand All @@ -59,52 +53,68 @@ upgrade: ## update the requirements/*.txt files with the latest packages satisfy
sed '/^[dD]jango==/d' requirements/test.txt > requirements/test.tmp
mv requirements/test.tmp requirements/test.txt

quality: ## check coding style with pycodestyle and pylint
tox -e quality

pii_check: ## check for PII annotations on all Django models
tox -e pii_check

piptools: ## install pinned version of pip-compile and pip-sync
pip install -r requirements/pip.txt
pip install -r requirements/pip-tools.txt

requirements: piptools ## install development environment requirements
requirements: clean_tox piptools ## install development environment requirements
pip-sync -q requirements/dev.txt requirements/private.*

dev.clean:
-docker rm $(REPO_NAME)-dev
-docker rmi $(REPO_NAME)-dev
test: clean ## run tests in the current virtualenv
pytest

dev.build:
docker build -t $(REPO_NAME)-dev $(CURDIR)
diff_cover: test ## find diff lines that need test coverage
diff-cover coverage.xml

dev.run: dev.clean dev.build ## Clean, build and run test image
docker run -p 8000:8000 -v $(CURDIR):/usr/local/src/$(REPO_NAME) --name $(REPO_NAME)-dev $(REPO_NAME)-dev
test-all: quality pii_check ## run tests on every supported Python/Django combination
tox
tox -e docs

validate: quality pii_check test ## run tests and quality checks

selfcheck: ## check that the Makefile is well-formed
@echo "The Makefile is well-formed."

## Localization targets

extract_translations: symlink_translations ## extract strings to be translated, outputting .po files
cd $(PACKAGE_NAME) && i18n_tool extract
mv $(EXTRACTED_DJANGO) $(EXTRACTED_TEXT)
if [ -f "$(EXTRACTED_DJANGOJS)" ]; then cat $(EXTRACTED_DJANGOJS) >> $(EXTRACTED_TEXT); rm $(EXTRACTED_DJANGOJS); fi
extract_translations: ## extract strings to be translated, outputting .mo files
rm -rf docs/_build
cd filesmanager && i18n_tool extract --no-segment

compile_translations: symlink_translations ## compile translation files, outputting .mo files for each supported language
cd $(PACKAGE_NAME) && i18n_tool generate
python manage.py compilejsi18n --namespace $(PACKAGE_NAME)i18n --output $(JS_TARGET)
compile_translations: ## compile translation files, outputting .po files for each supported language
cd filesmanager && i18n_tool generate

detect_changed_source_translations:
cd $(PACKAGE_NAME) && i18n_tool changed
cd filesmanager && i18n_tool changed

dummy_translations: ## generate dummy translation (.po) files
cd $(PACKAGE_NAME) && i18n_tool dummy
ifeq ($(OPENEDX_ATLAS_PULL),)
pull_translations: ## Pull translations from Transifex
tx pull -t -a -f --mode reviewed --minimum-perc=1
else
# Experimental: OEP-58 Pulls translations using atlas
pull_translations:
find filesmanager/conf/locale -mindepth 1 -maxdepth 1 -type d -exec rm -r {} \;
atlas pull $(OPENEDX_ATLAS_ARGS) translations/xblock-filesmanager/filesmanager/conf/locale:filesmanager/conf/locale
python manage.py compilemessages

build_dummy_translations: dummy_translations compile_translations ## generate and compile dummy translation files
@echo "Translations have been pulled via Atlas and compiled."
endif

validate_translations: build_dummy_translations detect_changed_source_translations ## validate translations
push_translations: ## push source translation files (.po) from Transifex
tx push -s

pull_translations: ## pull translations from transifex
cd $(PACKAGE_NAME) && i18n_tool transifex pull
dummy_translations: ## generate dummy translation (.po) files
cd filesmanager && i18n_tool dummy

push_translations: extract_translations ## push translations to transifex
cd $(PACKAGE_NAME) && i18n_tool transifex push
build_dummy_translations: extract_translations dummy_translations compile_translations ## generate and compile dummy translation files

symlink_translations:
if [ ! -d "$(TRANSLATIONS_DIR)" ]; then ln -s locale/ $(TRANSLATIONS_DIR); fi
validate_translations: build_dummy_translations detect_changed_source_translations ## validate translations

install_transifex_client: ## Install the Transifex client
# Instaling client will skip CHANGELOG and LICENSE files from git changes
Expand Down
7 changes: 7 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
from datetime import datetime
from subprocess import check_call

from django import setup as django_setup


def get_version(*file_paths):
"""
Expand All @@ -38,6 +40,9 @@ def get_version(*file_paths):
sys.path.append(REPO_ROOT)

VERSION = get_version('../filesmanager', '__init__.py')
# Configure Django for autodoc usage
os.environ['DJANGO_SETTINGS_MODULE'] = 'test_settings'
django_setup()

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
Expand Down Expand Up @@ -513,6 +518,8 @@ def get_version(*file_paths):
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {
'python': ('https://docs.python.org/3.8', None),
'django': ('https://docs.djangoproject.com/en/3.2/', 'https://docs.djangoproject.com/en/3.2/_objects/'),
'model_utils': ('https://django-model-utils.readthedocs.io/en/latest/', None),
}


Expand Down
2 changes: 1 addition & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.. xblock-filesmanager documentation top level file, created by
sphinx-quickstart on Tue Aug 22 11:58:46 2023.
sphinx-quickstart on Tue Nov 21 16:36:43 2023.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.

Expand Down
4 changes: 1 addition & 3 deletions filesmanager/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,4 @@
Init for the FilesManagerXBlock package.
"""

from .filesmanager import FilesManagerXBlock

__version__ = '0.4.0'
__version__ = '0.5.0'
28 changes: 28 additions & 0 deletions filesmanager/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""
filesmanager Django application initialization.
"""

from django.apps import AppConfig


class FilesManagerConfig(AppConfig):
"""
Configuration for the filesmanager Django application.
"""

name = 'filesmanager'

plugin_app = {
"settings_config": {
"lms.djangoapp": {
"common": {"relative_path": "settings.common"},
"test": {"relative_path": "settings.test"},
"production": {"relative_path": "settings.production"},
},
"cms.djangoapp": {
"common": {"relative_path": "settings.common"},
"test": {"relative_path": "settings.test"},
"production": {"relative_path": "settings.production"},
},
},
}
Loading