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

Add initial Windows support #29

Merged
merged 45 commits into from Oct 29, 2018
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
682dcf7
Add initial windows support
libre-man Oct 17, 2018
a84560f
Fix failing tests
libre-man Oct 17, 2018
2195fbb
Remove relative import
libre-man Oct 17, 2018
8fe2503
Use correct socket type
libre-man Oct 17, 2018
45096a0
Use correct fuse arguments
libre-man Oct 17, 2018
ee1dddd
Fix various mypy errors
libre-man Oct 17, 2018
c85baa6
Fix final test errors
libre-man Oct 17, 2018
26fba2f
Test code without mypy installed
libre-man Oct 17, 2018
4cb58da
Add update checker
libre-man Oct 17, 2018
d7fff8b
Add a simple GUI
libre-man Oct 21, 2018
fd6499b
Add version check to GUI
libre-man Oct 21, 2018
3e25156
Fix plugin socket for windows
libre-man Oct 21, 2018
224f0be
Minor fixes
libre-man Oct 22, 2018
d0ce127
Don't use getattr(obj, str)() pattern
libre-man Oct 22, 2018
298982b
Add warning when uploading in non-fixed mode
libre-man Oct 25, 2018
c546864
Add error handling
libre-man Oct 25, 2018
b4b6996
Add utils file
libre-man Oct 25, 2018
f7bf020
Fix setup.py
libre-man Oct 25, 2018
e4b5af9
Fix winfspy version
libre-man Oct 25, 2018
895aa7d
Fix version detection
libre-man Oct 25, 2018
031f6a3
Make parent directories
libre-man Oct 25, 2018
bca3024
Only show newer version when there is a newer version
libre-man Oct 25, 2018
353c811
Fix fs gui on windows
libre-man Oct 25, 2018
8b1f6f4
Fix mypy errors
libre-man Oct 26, 2018
d15e682
Fix issues raised by @olmokramer
libre-man Oct 27, 2018
9dcca6e
Fix file permissions on windows
libre-man Oct 27, 2018
8150eb3
Fix getting version info winfsp
libre-man Oct 27, 2018
d781f09
Fix cgapi-consumer file finding on windows
libre-man Oct 27, 2018
726d5bc
Fix get_file call in fs
libre-man Oct 27, 2018
6f98c3a
Fix file handling in api
libre-man Oct 27, 2018
9445e88
Add build files
libre-man Oct 28, 2018
c4544f8
Fix icon location
libre-man Oct 28, 2018
c5ced9c
Fix typo in installer.nsi
libre-man Oct 28, 2018
eea907f
Fix NSIS warning
libre-man Oct 28, 2018
9f10b70
Improve logo
libre-man Oct 28, 2018
2434013
Catch all exceptions when importing fuse
libre-man Oct 28, 2018
a4a6650
Fix more import errors
libre-man Oct 28, 2018
9a27382
Fix logging
libre-man Oct 28, 2018
b2f90ac
Update README
libre-man Oct 28, 2018
d879ac0
Improve help text
libre-man Oct 28, 2018
8cfe0ec
Rewrite thread code to QThread
libre-man Oct 28, 2018
d29c0f8
Fix remarks by @olmokramer
libre-man Oct 28, 2018
4a2f2d4
Change order of password checks
olmokramer Oct 28, 2018
3cc2f55
Merge branch 'feature/windows-support' of git://github.com/CodeGra-de…
olmokramer Oct 28, 2018
ffb4a29
Fix type errors
libre-man Oct 29, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Expand Up @@ -5,4 +5,5 @@ mount/
/.run_tests.sh
.cov2emacs.log
/.coverage
/dist/
/dist/
.mypy_cache/
7 changes: 4 additions & 3 deletions .travis.yml
Expand Up @@ -17,7 +17,7 @@ cache:

matrix:
include:
- python: "3.6-dev" # 3.6 development branch
- python: "3.7-dev" # 3.7 development branch

addons:
apt:
Expand All @@ -33,8 +33,7 @@ before_install:

install:
- pip install -U wheel
- pip install coveralls pytest-cov
- pip install codecov
- pip install coveralls pytest-cov codecov
- pip install .
- which cgfs
- pip install celery[redis]
Expand Down Expand Up @@ -62,6 +61,8 @@ before_script:

script:
- make test
- pip install mypy
- mypy codegra_fs

after_script:
cat server.log
Expand Down
9 changes: 9 additions & 0 deletions codegra_fs/__init__.py
@@ -0,0 +1,9 @@
# SPDX-License-Identifier: AGPL-3.0-only

__version__ = (0, 4, 0)
__author__ = 'Olmo Kramer, Thomas Schaper'
__email__ = 'info@CodeGra.de'
__license__ = 'AGPL-3.0-only'
__maintainer__ = 'CodeGrade'

import codegra_fs.utils as utils
37 changes: 25 additions & 12 deletions codegra_fs/api_consumer.py
@@ -1,11 +1,13 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: AGPL-3.0-only

import os
import sys
import json
import socket


def print_usage():
def print_usage() -> None:
print(
(
'Usage:\n'
Expand All @@ -20,7 +22,7 @@ def print_usage():
)


def recv(s):
def recv(s: socket.socket) -> str:
message = b''

while True:
Expand All @@ -32,7 +34,7 @@ def recv(s):
return message.decode()


def is_file(s, file):
def is_file(s: socket.socket, file: str) -> int:
s.send(
bytes(
json.dumps({
Expand All @@ -47,7 +49,7 @@ def is_file(s, file):
return 2


def get_comments(s, file):
def get_comments(s: socket.socket, file: str) -> int:
s.send(
bytes(
json.
Expand All @@ -72,7 +74,7 @@ def get_comments(s, file):
return 2


def delete_comment(s, file, line):
def delete_comment(s: socket.socket, file: str, line: int) -> int:
s.send(
bytes(
json.dumps(
Expand All @@ -90,7 +92,7 @@ def delete_comment(s, file, line):
return 2


def set_comment(s, file, line, message):
def set_comment(s: socket.socket, file: str, line: int, message: str) -> int:
s.send(
bytes(
json.dumps(
Expand All @@ -109,14 +111,18 @@ def set_comment(s, file, line, message):
return 2


def main():
path = '/'
def main() -> None:
if sys.platform.startswith('win32'):
path = ''
else:
path = '/'

if len(sys.argv) < 3:
print_usage()
sys.exit(1)

for p in os.path.abspath(sys.argv[2]).split('/'):
if not p:
for p in os.path.abspath(sys.argv[2]).split(os.sep):
if path and not p:
continue
path = os.path.join(path, p)
if os.path.isfile(os.path.join(path, '.api.socket')):
Expand All @@ -125,8 +131,15 @@ def main():
print('Socket not found', file=sys.stderr)
sys.exit(3)

s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.connect(open(os.path.join(path, '.api.socket'), 'r').read())
with open(os.path.join(path, '.api.socket'), 'r') as f:
socketfile_content = f.read().strip()

if sys.platform.startswith('win32'):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', int(socketfile_content)))
else:
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.connect(socketfile_content)

try:
if sys.argv[1] == 'set-comment':
Expand Down
44 changes: 34 additions & 10 deletions codegra_fs/cgapi.py
@@ -1,13 +1,18 @@
# -*- coding: utf-8 -*-
# SPDX-License-Identifier: AGPL-3.0-only

import typing as t
import logging
from enum import IntEnum
from functools import partial
from urllib.parse import quote

import requests

DEFAULT_CGAPI_BASE_URL = 'https://codegra.de/api/v1'

logger = logging.getLogger(__name__)


class APIRoutes():
def __init__(self, base, owner='auto'):
Expand All @@ -28,15 +33,15 @@ def get_submissions(self, assignment_id):
base=self.base, assignment_id=assignment_id
)

def get_files(self, submission_id):
def get_files(self, submission_id: int) -> str:
return ('{base}/submissions/{submission_id}'
'/files/?owner={owner}').format(
base=self.base,
submission_id=submission_id,
owner=self.owner,
)

def get_file(self, submission_id, path):
def get_file(self, submission_id: int, path: str) -> str:
return (
'{base}/submissions/{submission_id}/'
'files/?path={path}&owner={owner}'
Expand Down Expand Up @@ -141,7 +146,13 @@ def __str__(self): # pragma: no cover


class CGAPI():
def __init__(self, username, password, base=None, fixed=False):
def __init__(
self,
username: str,
password: str,
base: t.Optional[str]=None,
fixed: bool=False
) -> None:
owner = 'student' if fixed else 'auto'
self.routes = APIRoutes(base or DEFAULT_CGAPI_BASE_URL, owner)

Expand All @@ -164,6 +175,11 @@ def __init__(self, username, password, base=None, fixed=False):
self.s.headers = {
'Authorization': 'Bearer ' + self.access_token,
}
self.s.get = partial(self.s.get, timeout=3) # type: ignore
self.s.patch = partial(self.s.patch, timeout=3) # type: ignore
self.s.post = partial(self.s.post, timeout=3) # type: ignore
self.s.delete = partial(self.s.delete, timeout=3) # type: ignore
self.s.put = partial(self.s.put, timeout=3) # type: ignore

def _handle_response_error(self, request):
if request.status_code >= 400:
Expand Down Expand Up @@ -216,15 +232,15 @@ def rename_file(self, file_id, new_path):

return r.json()

def get_file(self, file_id):
def get_file(self, file_id: int) -> bytes:
url = self.routes.get_file_buf(file_id=file_id)
r = self.s.get(url)

self._handle_response_error(r)

return r.content

def patch_file(self, file_id, buf):
def patch_file(self, file_id: int, buf: bytes) -> t.Dict[str, t.Any]:
url = self.routes.get_file_buf(file_id=file_id)
r = self.s.patch(url, data=buf)

Expand Down Expand Up @@ -319,13 +335,21 @@ def get_submission(self, submission_id):

return r.json()

def set_submission(self, submission_id, grade=None, feedback=None):
def set_submission(
self,
submission_id: int,
grade: t.Union[None, float, str]=None,
feedback: t.Optional[bytes]=None
):
url = self.routes.set_submission(submission_id)
d = {}
d = {} # type: t.Dict[str, t.Union[bytes, float, None]]
if grade is not None:
d['grade'] = grade
if grade == 'delete':
d['grade'] = None
if grade == 'delete':
d['grade'] = None
else:
assert not isinstance(grade, str)
d['grade'] = grade

if feedback is not None:
d['feedback'] = feedback
r = self.s.patch(url, json=d)
Expand Down