
commit
908872467b
10 changed files with 628 additions and 0 deletions
@ -0,0 +1,135 @@
|
||||
usurpa.pdf |
||||
|
||||
# Configuration file, check config-example.py |
||||
config.py |
||||
|
||||
# For pycharm ide |
||||
.idea |
||||
|
||||
# Created by https://www.gitignore.io/api/python |
||||
# Edit at https://www.gitignore.io/?templates=python |
||||
|
||||
### Python ### |
||||
# Byte-compiled / optimized / DLL files |
||||
__pycache__/ |
||||
*.py[cod] |
||||
*$py.class |
||||
|
||||
# C extensions |
||||
*.so |
||||
|
||||
# Distribution / packaging |
||||
.Python |
||||
build/ |
||||
develop-eggs/ |
||||
dist/ |
||||
downloads/ |
||||
eggs/ |
||||
.eggs/ |
||||
lib/ |
||||
lib64/ |
||||
parts/ |
||||
sdist/ |
||||
var/ |
||||
wheels/ |
||||
pip-wheel-metadata/ |
||||
share/python-wheels/ |
||||
*.egg-info/ |
||||
.installed.cfg |
||||
*.egg |
||||
MANIFEST |
||||
|
||||
# PyInstaller |
||||
# Usually these files are written by a python script from a template |
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it. |
||||
*.manifest |
||||
*.spec |
||||
|
||||
# Installer logs |
||||
pip-log.txt |
||||
pip-delete-this-directory.txt |
||||
|
||||
# Unit test / coverage reports |
||||
htmlcov/ |
||||
.tox/ |
||||
.nox/ |
||||
.coverage |
||||
.coverage.* |
||||
.cache |
||||
nosetests.xml |
||||
coverage.xml |
||||
*.cover |
||||
.hypothesis/ |
||||
.pytest_cache/ |
||||
|
||||
# Translations |
||||
*.mo |
||||
*.pot |
||||
|
||||
# Django stuff: |
||||
*.log |
||||
local_settings.py |
||||
db.sqlite3 |
||||
|
||||
# Flask stuff: |
||||
instance/ |
||||
.webassets-cache |
||||
|
||||
# Scrapy stuff: |
||||
.scrapy |
||||
|
||||
# Sphinx documentation |
||||
docs/_build/ |
||||
|
||||
# PyBuilder |
||||
target/ |
||||
|
||||
# Jupyter Notebook |
||||
.ipynb_checkpoints |
||||
|
||||
# IPython |
||||
profile_default/ |
||||
ipython_config.py |
||||
|
||||
# pyenv |
||||
.python-version |
||||
|
||||
# celery beat schedule file |
||||
celerybeat-schedule |
||||
|
||||
# SageMath parsed files |
||||
*.sage.py |
||||
|
||||
# Environments |
||||
.env |
||||
.venv |
||||
env/ |
||||
venv/ |
||||
ENV/ |
||||
env.bak/ |
||||
venv.bak/ |
||||
|
||||
# Spyder project settings |
||||
.spyderproject |
||||
.spyproject |
||||
|
||||
# Rope project settings |
||||
.ropeproject |
||||
|
||||
# mkdocs documentation |
||||
/site |
||||
|
||||
# mypy |
||||
.mypy_cache/ |
||||
.dmypy.json |
||||
dmypy.json |
||||
|
||||
# Pyre type checker |
||||
.pyre/ |
||||
|
||||
### Python Patch ### |
||||
.venv/ |
||||
|
||||
# End of https://www.gitignore.io/api/python |
||||
|
||||
|
@ -0,0 +1,41 @@
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMMWN0dc,.. ..,cx0NMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM |
||||
MMMMMMMMMMMMMMMMMMMMMWNOdc'. .,cdONMMMMMMMMMMMMMMMMMMMMMMMMMMM |
||||
MMMMMMMMMMMMMMMMMMMXkc' .'ckXMMMMMMMMMMMMWNXK0OkdoloO |
||||
MMMMMMMMMMMMMMMMW0l' 'l0WMMMWKdlc:,'... cX |
||||
MMMMMMMMMMMMMMWO:. .,:ldxkOOOkkxdoc;.. .c0WMMXl. cXM |
||||
MMMMMMMMMMMMMKc. .;oOXWMMMMMMMMMMMMMMWN0dc. .lKNOc. cXMM |
||||
MMMMMMMMMMMWk' ,dKWMMMMMMMMMMMMMMMMMMMMMMWXk:. .' cXMMM |
||||
MMMMMMMMMMNo. ,kNMMMMMMMMMMMMMMMMMMMMMMMMMMMMW0c. cXMMMM |
||||
MMMMMMMMMNl. .dNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWx. .;dx;.cXMMMMM |
||||
MMMMMMMMWd. ,OWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMW0o, .l0WMMN0XMMMMMM |
||||
MMMMMMMMO. ,0MMMMMMMMMMMMMMMMWXXWMMMMMMMMMMWXx;. 'OMMMMMMMMMMMMM |
||||
MMMMMMMNc .OMMMMMMMMMMMMMMWXx:..lKWMMMMMMNkc. lNMMMMMMMMMMMM |
||||
MMMMMMMO. oWMMMMMMMMMMMMNOc. .oOXWW0o, ';. '0MMMMMMMMMMMM |
||||
MMMMMMWd. .OMMMMMMMMMMN0o' 'c;. .:kXX: .xMMMMMMMMMMMM |
||||
MMMMMMWo ,KMMMMMMMWKd;. ,oKWMMWl dWMMMMMMMMMMM |
||||
MMMMMMWo ,KMMMMWXx:. .cONMMMMMWl dWMMMMMMMMMMM |
||||
MMMMMMWd. '0MMNOc. .cxx; .;xXWMMMMMMMNc .xMMMMMMMMMMMM |
||||
MMMMMMMO. .o0o, .:xXWMMNx, 'o0WMMMMMMMMMM0' '0MMMMMMMMMMMM |
||||
MMMMMMMNc .. .;dKWMMMMMMMXd:;ckNMMMMMMMMMMMMNl lNMMMMMMMMMMMM |
||||
MMMMMMMMO. .,d0WMMMMMMMMMMMMWWWMMMMMMMMMMMMMWx. '0MMMMMMMMMMMMM |
||||
MMMMMMMNx' ,o0WMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWx. .xWMMMMMMMMMMMMM |
||||
MMMMW0o, ,kNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXl. .dNMMMMMMMMMMMMMM |
||||
MWKd;. .lKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNx' .dNMMMMMMMMMMMMMMM |
||||
k:. .. .cONMMMMMMMMMMMMMMMMMMMMMMMMWKd, ,OWMMMMMMMMMMMMMMMM |
||||
; .:xKKl. .,oOXWMMMMMMMMMMMMMMMMMN0x:. .oXMMMMMMMMMMMMMMMMMM |
||||
Xo. .;dKWMMMW0c. .;ldO0KXNNNXXK0Oxo:'. .c0WMMMMMMMMMMMMMMMMMMM |
||||
MWO:;o0WMMMMMMMMW0o' .......... 'oKWMMMMMMMMMMMMMMMMMMMMM |
||||
MMMWWMMMMMMMMMMMMMMNkl'. .,lkNMMMMMMMMMMMMMMMMMMMMMMMM |
||||
MMMMMMMMMMMMMMMMMMMMMMN0dc,. ..,cd0NMMMMMMMMMMMMMMMMMMMMMMMMMMM |
||||
MMMMMMMMMMMMMMMMMMMMMMMMMWN0xl;.. ..;lx0NMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM |
||||
|
||||
Welcome to usurpa-api ! |
||||
|
||||
# Usurpa-api |
||||
|
||||
This api is based on the popular, ancient and usable squat schedule: |
||||
|
||||
https://usurpa.squat.net |
||||
|
||||
The objective of the api is to modernize the work of usurpa mates to be more adapted to our times. |
||||
|
@ -0,0 +1,31 @@
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMMWN0dc,.. ..,cx0NMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM |
||||
MMMMMMMMMMMMMMMMMMMMMWNOdc'. .,cdONMMMMMMMMMMMMMMMMMMMMMMMMMMM |
||||
MMMMMMMMMMMMMMMMMMMXkc' .'ckXMMMMMMMMMMMMWNXK0OkdoloO |
||||
MMMMMMMMMMMMMMMMW0l' 'l0WMMMWKdlc:,'... cX |
||||
MMMMMMMMMMMMMMWO:. .,:ldxkOOOkkxdoc;.. .c0WMMXl. cXM |
||||
MMMMMMMMMMMMMKc. .;oOXWMMMMMMMMMMMMMMWN0dc. .lKNOc. cXMM |
||||
MMMMMMMMMMMWk' ,dKWMMMMMMMMMMMMMMMMMMMMMMWXk:. .' cXMMM |
||||
MMMMMMMMMMNo. ,kNMMMMMMMMMMMMMMMMMMMMMMMMMMMMW0c. cXMMMM |
||||
MMMMMMMMMNl. .dNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWx. .;dx;.cXMMMMM |
||||
MMMMMMMMWd. ,OWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMW0o, .l0WMMN0XMMMMMM |
||||
MMMMMMMMO. ,0MMMMMMMMMMMMMMMMWXXWMMMMMMMMMMWXx;. 'OMMMMMMMMMMMMM |
||||
MMMMMMMNc .OMMMMMMMMMMMMMMWXx:..lKWMMMMMMNkc. lNMMMMMMMMMMMM |
||||
MMMMMMMO. oWMMMMMMMMMMMMNOc. .oOXWW0o, ';. '0MMMMMMMMMMMM |
||||
MMMMMMWd. .OMMMMMMMMMMN0o' 'c;. .:kXX: .xMMMMMMMMMMMM |
||||
MMMMMMWo ,KMMMMMMMWKd;. ,oKWMMWl dWMMMMMMMMMMM |
||||
MMMMMMWo ,KMMMMWXx:. .cONMMMMMWl dWMMMMMMMMMMM |
||||
MMMMMMWd. '0MMNOc. .cxx; .;xXWMMMMMMMNc .xMMMMMMMMMMMM |
||||
MMMMMMMO. .o0o, .:xXWMMNx, 'o0WMMMMMMMMMM0' '0MMMMMMMMMMMM |
||||
MMMMMMMNc .. .;dKWMMMMMMMXd:;ckNMMMMMMMMMMMMNl lNMMMMMMMMMMMM |
||||
MMMMMMMMO. .,d0WMMMMMMMMMMMMWWWMMMMMMMMMMMMMWx. '0MMMMMMMMMMMMM |
||||
MMMMMMMNx' ,o0WMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWx. .xWMMMMMMMMMMMMM |
||||
MMMMW0o, ,kNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXl. .dNMMMMMMMMMMMMMM |
||||
MWKd;. .lKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNx' .dNMMMMMMMMMMMMMMM |
||||
k:. .. .cONMMMMMMMMMMMMMMMMMMMMMMMMWKd, ,OWMMMMMMMMMMMMMMMM |
||||
; .:xKKl. .,oOXWMMMMMMMMMMMMMMMMMN0x:. .oXMMMMMMMMMMMMMMMMMM |
||||
Xo. .;dKWMMMW0c. .;ldO0KXNNNXXK0Oxo:'. .c0WMMMMMMMMMMMMMMMMMMM |
||||
MWO:;o0WMMMMMMMMW0o' .......... 'oKWMMMMMMMMMMMMMMMMMMMMM |
||||
MMMWWMMMMMMMMMMMMMMNkl'. .,lkNMMMMMMMMMMMMMMMMMMMMMMMM |
||||
MMMMMMMMMMMMMMMMMMMMMMN0dc,. ..,cd0NMMMMMMMMMMMMMMMMMMMMMMMMMMM |
||||
MMMMMMMMMMMMMMMMMMMMMMMMMWN0xl;.. ..;lx0NMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM |
||||
|
@ -0,0 +1,14 @@
|
||||
#!/usr/bin/python |
||||
|
||||
# Name of the application |
||||
APP_BASE_NAME = 'usurpa-api' |
||||
|
||||
# File to update |
||||
USURPA_URL = 'https://usurpa.squat.net/usurpa.pdf' |
||||
USURPA_DOWNLOAD_PATH = 'usurpa-proves1.ods' |
||||
|
||||
# Gancio |
||||
GANCIO_URL = "http://localhost:13120" |
||||
# TODO: Seguro que hay una forma mas segura de hacer esto, pero lo mirare mas adelante |
||||
GUSER = "example@example.es" |
||||
GPASSWORD = "examplepassword" |
@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env python3 |
||||
|
||||
from models import GancioEvent |
||||
import requests |
||||
import config |
||||
|
||||
# Hace una petición POST a /api/event con los datos de evento |
||||
def CreateEvent(sendData,token): |
||||
try: |
||||
headers = {'Authorization': 'Bearer ' + token } |
||||
url = config.GANCIO_URL + "/api/event" |
||||
resp = requests.post(url,files = sendData,headers = headers) |
||||
if resp.status_code == 200: |
||||
print("Se ha creado el evento con exito") |
||||
except Exception as e: |
||||
print("Error doing the request to the api:") |
||||
print(str(e)) |
||||
|
||||
def GetLoginToken(): |
||||
url = config.GANCIO_URL |
||||
payload = {"username" : config.GUSER , "password" : config.GPASSWORD , "grant_type": "password" , "client_id": "self"} |
||||
resp = requests.post(url,data= payload) |
||||
return resp.json()["access_token"] |
||||
|
||||
def UploadEventGancio(Event): |
||||
try: |
||||
event = GancioEvent(Event["title"],Event["description"],Event["squat"],Event["street"],Event["start_datetime"],Event["end_datetime"],"False") |
||||
token = GetLoginToken() |
||||
sendData = event.getMultipartFormData() |
||||
CreateEvent(sendData,token) |
||||
except Exception as e: |
||||
print("Error creating the event in gancio") |
||||
print(str(e)) |
||||
return |
||||
|
||||
|
||||
#GancioEvent = {"title": "" , "description", "placename": "", "placeaddress": "", "startdatetime", "", "end_datetime": "" } |
@ -0,0 +1,97 @@
|
||||
import config |
||||
|
||||
# squatNameExceptions = config.NAME_EXCEPTIONS |
||||
# zones = config.REGIONAL_ZONES |
||||
|
||||
class UsurpaSection(object): |
||||
def __init__(self, title): |
||||
self.title = title |
||||
self.rows = [] |
||||
|
||||
def addRow(self, row): |
||||
self.rows.append(row) |
||||
|
||||
|
||||
class Squat(object): |
||||
def __init__(self, row): |
||||
self.row = row |
||||
# The ezodf cell object should have 3 lines corresponding to |
||||
# 1. Squat name |
||||
# 2. Address |
||||
# 3. Metro station |
||||
cellSplit = row[0].value.split("\n") |
||||
self.name = cellSplit[0] if 0 < len(cellSplit) else None |
||||
self.address = cellSplit[1] if 1 < len(cellSplit) else None |
||||
self.metro = cellSplit[2] if 2 < len(cellSplit) else None |
||||
|
||||
# Check if has extra information (a row split) |
||||
self.hasRowSpan = True if row[0].span[0] > 1 else False |
||||
self.rowSpan = row[0].span[0] |
||||
self.additionalInfo = [] |
||||
|
||||
# Initialize th 7 days of the week |
||||
self.events = [None] * 7 |
||||
|
||||
|
||||
class RegionalZone (object): |
||||
|
||||
def __init__(self, name=None): |
||||
self.name = name |
||||
self.rows = [] |
||||
self.squatList = [] |
||||
|
||||
def addRow(self, row): |
||||
""" |
||||
Add a row object [] into the sets of self.rows[] |
||||
:param row: |
||||
:return: |
||||
""" |
||||
self.rows.append(row) |
||||
|
||||
# TODO: DRY this function is basically the same as parser.parseCSV |
||||
def generateSquats(self): |
||||
squat = None |
||||
for row in self.rows: |
||||
squatName = Squat.isSquatName(row[0]) |
||||
if squatName: |
||||
squat = Squat(squatName) |
||||
self.squatList.append(squat) |
||||
if squat is not None: |
||||
squat.addRow(row) |
||||
|
||||
# TODO: Try to do this without making loop |
||||
# Check if a row contains a zone name defined on config file |
||||
@classmethod |
||||
def checkIfIsZone(cls, row): |
||||
for zone in zones: |
||||
if zone in row: |
||||
return zone |
||||
return False |
||||
|
||||
|
||||
class GancioEvent: |
||||
|
||||
def __init__(self,title,description,place_name,place_address,start_datetime,end_datetime): |
||||
self.title = str(title) |
||||
self.description = str(description) |
||||
self.place_name = str(place_name) |
||||
self.place_address = str(place_address) |
||||
self.start_datetime = int(start_datetime) |
||||
self.end_datetime = int(end_datetime) |
||||
self.multidate = "False" |
||||
|
||||
def getJson(self): |
||||
EventDict = {} |
||||
EventDict["title"] = self.title |
||||
EventDict["description"] = self.description |
||||
EventDict["place_name"] = self.place_name |
||||
EventDict["place_address"] = self.place_address |
||||
EventDict["start_datetime"] = self.start_datetime |
||||
EventDict["multidate"] = self.multidate |
||||
return EventDict |
||||
|
||||
def getMultipartFormData(self): |
||||
body = {} |
||||
for atribute in self.__dict__.keys(): |
||||
body[atribute] = (None, self.__dict__[atribute]) |
||||
return body |
@ -0,0 +1,133 @@
|
||||
import sys |
||||
|
||||
import config, ezodf |
||||
from models import RegionalZone, UsurpaSection, Squat |
||||
import lxml.etree as etree |
||||
from ezodf.styles import OfficeAutomaticStyles |
||||
|
||||
CELL_WIDTH=8 # number of cells to iterate when analize a row |
||||
appName = config.APP_BASE_NAME |
||||
usurpaOds = config.USURPA_DOWNLOAD_PATH |
||||
sectionList = {} |
||||
squatList = {} |
||||
days = [] # Used to store the days |
||||
|
||||
|
||||
class AutomaticStyles: |
||||
|
||||
_TAG = "{urn:oasis:names:tc:opendocument:xmlns:office:1.0}automatic-styles" |
||||
|
||||
_PROP_PREFIX='{urn:oasis:names:tc:opendocument:xmlns:style:1.0}' |
||||
TABLE_CELL_PROPERTIES = _PROP_PREFIX+"table-cell-properties" |
||||
PARAGRAPH_PROPERTIES = _PROP_PREFIX+"paragraph-properties" |
||||
TEXT_PROPERTIES = _PROP_PREFIX+"text-properties style" |
||||
|
||||
def __init__(self, xmlnode): |
||||
xmlstyles = next((child for child in xmlnode if child.tag == self._TAG), None) |
||||
self.automaticStyles = OfficeAutomaticStyles(xmlstyles) |
||||
|
||||
def getStyleProperties(self, styleName, prop): |
||||
xmlstyle = self.automaticStyles._find(styleName) |
||||
if xmlstyle is None: return None |
||||
return next((child for child in xmlstyle if child.tag == prop ), None) |
||||
|
||||
def getBackgroundColor(self, styleName): |
||||
tag = '{urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0}background-color' |
||||
cellStyle = self.getStyleProperties(styleName, AutomaticStyles.TABLE_CELL_PROPERTIES) |
||||
return cellStyle.get(tag) if cellStyle is not None else None |
||||
|
||||
|
||||
|
||||
def parse(input=usurpaOds): |
||||
|
||||
print("# Parsig", input) |
||||
|
||||
doc = ezodf.opendoc(input) |
||||
if doc.doctype == 'odt': |
||||
|
||||
# Get styles |
||||
print("* Parsing styles") |
||||
styles = AutomaticStyles(doc.filemanager.get_xml_element('content.xml')) |
||||
|
||||
print("* Parsing sections") |
||||
# sheet = doc.sheets[0] |
||||
# sheet = doc.body.filter(kind='Table') |
||||
# print(doc.body.__dict__) |
||||
sheet = None |
||||
for obj in doc.body: |
||||
if type(obj) == ezodf.table.Table: |
||||
sheet = obj |
||||
break |
||||
|
||||
section = None |
||||
for rindex, row in enumerate(sheet.rows()): |
||||
stylename = row[0].style_name |
||||
bgColor = styles.getBackgroundColor(stylename) |
||||
print(row[0].value) |
||||
|
||||
# If bgColor is black mark the beginning of a new UsurpaSection |
||||
if bgColor == "#000000": |
||||
# Store old section |
||||
if section is not None: sectionList[section.title] = section |
||||
section = UsurpaSection(row[0].value) |
||||
actualSection = len(sectionList) |
||||
|
||||
# Now lets analize the entire row |
||||
if section is not None: |
||||
# todo: First section. Demonstrations, info usurpa number and week |
||||
if actualSection == 0: |
||||
pass |
||||
# todo: "Jornades i actes ocasionals" |
||||
elif actualSection == 1: |
||||
# The first cell is the title and the second is spanned until the end with the event info |
||||
pass |
||||
# Days and their position |
||||
elif actualSection == 2: |
||||
for i in range(1, CELL_WIDTH): |
||||
days.append(row[i].value) |
||||
# Squats |
||||
elif actualSection > 2: |
||||
# If is not the header of the section |
||||
if bgColor != "#000000": |
||||
# First create the Squat object... Oh yeah |
||||
if row[0].value is None: continue |
||||
squat = Squat(row) |
||||
# Then parse the day events |
||||
for i in range(1, CELL_WIDTH): |
||||
# todo: fix the template because there are two spanned cells that are not visible |
||||
print(days) |
||||
day = i-1 # The day of the week (this loop starts at 1 and the array of days inside squat at 0) |
||||
print(days[day]) |
||||
print(row[i].value) |
||||
print(row[i].span) |
||||
|
||||
if squat.events[day] is None: |
||||
# If the cell is spanned to more than one days copy the event on this days |
||||
for span in range(0, row[i].span[1]): squat.events[day + span] = row[i].value |
||||
# Check if has aditional info |
||||
if squat.hasRowSpan: |
||||
for i in range(1, squat.rowSpan): |
||||
squat.additionalInfo.append(sheet.row(rindex+1)[1].value) |
||||
squatList[squat.name] = squat |
||||
|
||||
section.addRow(row) |
||||
|
||||
print("* Squats found:", len(squatList)) |
||||
|
||||
# for k,v in sectionList.items(): |
||||
# print(k) |
||||
|
||||
else: |
||||
print("Bad format for", input) |
||||
raise |
||||
|
||||
|
||||
d = 2 |
||||
s = "AT. LLIB. GRÀCIA" |
||||
print(squatList[s].name, ": ", days[d], squatList[s].events[d]) |
||||
print("INFO adicional: "+"".join(squatList[s].additionalInfo if squatList[s].hasRowSpan else "No te informacio adicional")) |
||||
|
||||
d=3 |
||||
s="HORT VALLCARCA" |
||||
print(squatList[s].name, ": ", days[d], squatList[s].events[d]) |
||||
print("INFO adicional: "+"".join(squatList[s].additionalInfo if squatList[s].hasRowSpan else "No te informacio adicional")) |
@ -0,0 +1,59 @@
|
||||
import sys, getopt, os, time |
||||
from datetime import datetime |
||||
import config |
||||
import urllib.request |
||||
|
||||
appName = config.APP_BASE_NAME |
||||
usurpaURL = config.USURPA_URL |
||||
usurpaDownloadPath = config.USURPA_DOWNLOAD_PATH |
||||
|
||||
def isUsurpadownloaded(): |
||||
return os.path.isfile(usurpaDownloadPath) |
||||
|
||||
def getConnection(url = usurpaURL): |
||||
return urllib.request.urlopen(url, timeout=30) |
||||
|
||||
# Get last modified attribure of remote url |
||||
def getRemoteLastModified(conn): |
||||
return datetime.strptime(conn.headers['last-modified'], '%a, %d %b %Y %H:%M:%S GMT') |
||||
|
||||
# Get last modified of local file |
||||
def getLocalLastModified(file): |
||||
if not os.path.isfile(file): |
||||
return False |
||||
stat = os.stat(file) |
||||
try: |
||||
return datetime.fromtimestamp(stat.st_birthtime) |
||||
except AttributeError: |
||||
# We're probably on Linux. No easy way to get creation dates here, |
||||
# so we'll settle for when its content was last modified. |
||||
return datetime.fromtimestamp(stat.st_mtime) |
||||
|
||||
def downloadUsurpa(url=usurpaURL, downloadPath = usurpaDownloadPath): |
||||
print ("- Start download of ", usurpaURL ) |
||||
# Download the file |
||||
urllib.request.urlretrieve(url, downloadPath) |
||||
# Set modification date |
||||
t = time.mktime(getRemoteLastModified(getConnection()).timetuple()) |
||||
os.utime(usurpaDownloadPath, (t, t)) |
||||
|
||||
def isUsurpaUpdated(remote, local): |
||||
if remote == local: |
||||
return True |
||||
return False |
||||
|
||||
def updateUsurpa(output=usurpaDownloadPath): |
||||
print("# ", appName,"check for updates ", ) |
||||
try: |
||||
if not isUsurpadownloaded: |
||||
print("- No ", appName," file found, proceed to download on\n", output) |
||||
downloadUsurpa(usurpaURL, downloadPath=output) |
||||
elif not isUsurpaUpdated(getRemoteLastModified(getConnection()), getLocalLastModified(output)): |
||||
print("- ", appName," is not updated, proceed to update: \n", output) |
||||
downloadUsurpa(usurpaURL, downloadPath=output) |
||||
print(appName, "updated succesfully") |
||||
print("Done.") |
||||
else: |
||||
print(appName, "was already updated") |
||||
except: |
||||
raise Exception("Error: Failed to update usurpa") |
Loading…
Reference in new issue