[1.9.13]: see changelog
This commit is contained in:
parent
fed0227968
commit
171de8808c
|
@ -9,6 +9,12 @@ Tyto - Littérateur
|
|||
|
||||
# CURRENTLY IN DEV !
|
||||
|
||||
## [1.9.13]
|
||||
- Check: One-Line needed tags, titles
|
||||
- Added first stats
|
||||
- move ini template from tyto to domain for domain config file
|
||||
- Check valid date in article and form domain date
|
||||
|
||||
## [1.9.12]
|
||||
- preparing check process : head tags in article
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env python3
|
||||
# Version: 1.9.12
|
||||
# Updated: 2023-09-30 1696082419
|
||||
# Version: 1.9.13
|
||||
# Updated: 2023-10-01 1696117427
|
||||
# Tyto - Littérateur
|
||||
|
||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -33,6 +33,8 @@
|
|||
#--------------------------
|
||||
|
||||
import sys
|
||||
from dateutil.parser import parse
|
||||
|
||||
import args, domain, langs, debug, post, tools
|
||||
|
||||
|
||||
|
@ -61,8 +63,7 @@ def manage(action, target):
|
|||
|
||||
# target is not "all"
|
||||
ready()
|
||||
if target.endswith(".tyto"):
|
||||
is_article(target)
|
||||
target.endswith(".tyto") and is_article(target)
|
||||
|
||||
|
||||
#================================#
|
||||
|
@ -70,29 +71,24 @@ def manage(action, target):
|
|||
# Also used with multiple (loop) #
|
||||
#--------------------------------#
|
||||
def is_article(target):
|
||||
if not post.is_article(target):
|
||||
if args.multiple:
|
||||
return # Let other articles pass
|
||||
|
||||
sys.exit(post.error)
|
||||
|
||||
validators()
|
||||
if post.error != 0:
|
||||
if args.targets:
|
||||
return # Let other articles pass
|
||||
|
||||
sys.exit(post.error)
|
||||
|
||||
print("pass", post.error, args.multiple)
|
||||
valid(target)
|
||||
|
||||
print("pass", post.error, args.targets)
|
||||
print("chk_date", chk_date)
|
||||
print("post.stats_comments =", post.stats_comments)
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
def validators():
|
||||
def valid(target):
|
||||
targets = args.targets
|
||||
|
||||
# Target is a tyto article
|
||||
post.is_article(target) or tools.exit(targets, post.error)
|
||||
|
||||
# One Line targs in head_contents
|
||||
post.error == 0 and ol_tags() or tools.exit(targets, post.error)
|
||||
|
||||
post.error == 0 and titles() or tools.exit(targets, post.error)
|
||||
|
||||
|
||||
#===========================================#
|
||||
|
@ -102,10 +98,16 @@ def multiple_targets():
|
|||
ready()
|
||||
|
||||
|
||||
#=======================#
|
||||
# check header contents #
|
||||
#-----------------------#
|
||||
#==============#
|
||||
# check header #===============================================================
|
||||
#==============#
|
||||
#======================#
|
||||
# One Line needed tags #
|
||||
#----------------------#
|
||||
def ol_tags():
|
||||
global sitemap
|
||||
|
||||
sitemap = "True"
|
||||
for ln, line in enumerate(post.head_contents.rsplit("\n"), 1):
|
||||
if not line or line.isspace() or line.startswith("#"): continue
|
||||
|
||||
|
@ -125,15 +127,22 @@ def ol_tags():
|
|||
|
||||
elif not post.tags[1] and line.startswith(post.tags[0]):
|
||||
post.tags = (post.tags[0], ol_tag_value(line, True))
|
||||
|
||||
elif line.startswith(post.nositemap):
|
||||
sitemap = "False"
|
||||
|
||||
|
||||
# Sets are done from loop
|
||||
# Check if tag value exists
|
||||
# =========================
|
||||
if not is_ol_tag(post.title[0], post.title[1]): return
|
||||
if not is_ol_tag(post.about[0], post.about[1]): return
|
||||
if not is_ol_tag(post.date[0], post.date[1]): return
|
||||
if not is_ol_tag(post.author[0], post.author[1]): return
|
||||
if not is_ol_tag(post.tags[0], post.tags[1]): return
|
||||
if not is_ol_tag(post.date[0], post.date[1]): return False
|
||||
if not is_valid_date(post.date[1]): return False
|
||||
if not is_ol_tag(post.title[0], post.title[1]): return False
|
||||
if not is_ol_tag(post.about[0], post.about[1]): return False
|
||||
if not is_ol_tag(post.author[0], post.author[1]): return False
|
||||
if not is_ol_tag(post.tags[0], post.tags[1]): return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
#===========================================#
|
||||
|
@ -144,7 +153,7 @@ def ol_tags():
|
|||
def ol_tag_value(line, commas):
|
||||
value = line.rsplit(":")[1].lstrip()
|
||||
|
||||
# reformat comma separated items, removing first space
|
||||
# reformat comma separated items, removing first spaces
|
||||
if commas:
|
||||
tuple_values = value.rsplit(",")
|
||||
value = ""
|
||||
|
@ -162,15 +171,57 @@ def ol_tag_value(line, commas):
|
|||
#---------------------------#
|
||||
def is_ol_tag(tag, value):
|
||||
if not value:
|
||||
post.error = 51
|
||||
debug.out(51, "%s ?"%tag, post.uri, True, 2, False)
|
||||
post.error = debug.out(51, "%s ?"%tag, post.uri, True, 2, False)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
def valid_date():
|
||||
|
||||
#======================================#
|
||||
# Check validity date #
|
||||
# set date of check (YYYY-MM-DD H:M:S) #
|
||||
# Also set epoch date #
|
||||
# Return True/False #
|
||||
#--------------------------------------#
|
||||
def is_valid_date(date):
|
||||
global chk_date
|
||||
|
||||
try:
|
||||
parse(date)
|
||||
chk_date = tools.nowdate()
|
||||
return True
|
||||
except:
|
||||
post.error = debug.out(50, "%s"%date, post.uri, True, 2, False)
|
||||
return False
|
||||
|
||||
|
||||
#===============#
|
||||
# check article #==============================================================
|
||||
#===============#
|
||||
#============================#
|
||||
# Check optional title tags #
|
||||
# Count tyto + html comments #
|
||||
# Return True/False #
|
||||
#----------------------------#
|
||||
def titles():
|
||||
for ln, line in enumerate(post.text_contents.rsplit("\n"),
|
||||
post.head_lines + 1):
|
||||
if not line or line.isspace():
|
||||
continue
|
||||
|
||||
if line.startswith(post.tyto_titles):
|
||||
if not line[3:]:
|
||||
post.error = \
|
||||
debug.out(52, "%s. %s ?"%(ln, line), post.uri, True, 2, False)
|
||||
return False
|
||||
post.stats_titles += 1
|
||||
|
||||
elif line[1].isdigit() and int(line[1]) >= 6:
|
||||
post.error = \
|
||||
debug.out(52, "%s) %s..."%(ln, line[0:10]), post.uri, True, 1, False)
|
||||
return False
|
||||
|
||||
elif line.startswith(post.text_comments):
|
||||
post.stats_comments += 1
|
||||
|
||||
return True
|
||||
|
|
|
@ -49,10 +49,11 @@ import langs, args
|
|||
def out(nbr, var, val, show, color, stop):
|
||||
args.get_options()
|
||||
if not show:
|
||||
show = args.dlogs or args.erron and color > 0 # Show only warn and error logs
|
||||
# Show only warn and error logs
|
||||
show = args.dlogs or args.erron and color > 0
|
||||
|
||||
if not show:
|
||||
return
|
||||
return nbr
|
||||
|
||||
# COlors
|
||||
CS = '\033[0;0m' # Unset
|
||||
|
@ -89,6 +90,7 @@ def out(nbr, var, val, show, color, stop):
|
|||
23 : langs.logs.err_post_empty,
|
||||
50 : langs.logs.err_date,
|
||||
51 : langs.logs.err_post_data,
|
||||
52 : langs.logs.err_post_title,
|
||||
# WARNINGS (100-200)
|
||||
100 : langs.logs.warn_no_dom,
|
||||
101 : langs.logs.domain_created,
|
||||
|
@ -126,4 +128,6 @@ def out(nbr, var, val, show, color, stop):
|
|||
if nbr >= 200:
|
||||
nbr = 0
|
||||
sys.exit(nbr)
|
||||
|
||||
return nbr
|
||||
|
||||
|
|
|
@ -32,7 +32,9 @@
|
|||
# file program :
|
||||
#--------------------------
|
||||
|
||||
import os, re, configparser
|
||||
import os, re
|
||||
from dateutil.parser import parse
|
||||
|
||||
import debug, domain, langs, tools
|
||||
|
||||
|
||||
|
@ -53,11 +55,8 @@ def ask(q, yes_only, default):
|
|||
if yes_only:
|
||||
expected = langs.logs.ok
|
||||
|
||||
try:
|
||||
answer = input(q)
|
||||
except KeyboardInterrupt:
|
||||
print("")
|
||||
maybe_later(expected, "?")
|
||||
try: answer = input(q)
|
||||
except KeyboardInterrupt: print("") ; maybe_later(expected, "?")
|
||||
|
||||
# return default answer if exists
|
||||
if not answer:
|
||||
|
@ -71,6 +70,7 @@ def ask(q, yes_only, default):
|
|||
for ok in langs.logs.ok:
|
||||
if answer.lower() == ok.lower():
|
||||
return True
|
||||
|
||||
maybe_later(expected, answer)
|
||||
|
||||
return answer
|
||||
|
@ -123,30 +123,21 @@ def ask_domain_title(update):
|
|||
#---------------------------#
|
||||
def ask_domain_date(update):
|
||||
try: date = domain.cf.get("DOMAIN", "date")
|
||||
except: date = "YYYY[-MM-DD]"
|
||||
except: date = "YYYY[-MM][-DD]"
|
||||
|
||||
example = date or "YYYY[-MM-DD]"
|
||||
example = date
|
||||
|
||||
q = "> %s (%s)%s "%(langs.logs.domain_date, example, langs.logs.q)
|
||||
answer = ask(q, False, date)
|
||||
|
||||
# Check date format (not valid date)
|
||||
test = True
|
||||
tuple_date = answer.rsplit("-")
|
||||
tuple_len = len(tuple_date)
|
||||
for i in range(tuple_len):
|
||||
if i == 0:
|
||||
if len(tuple_date[i]) != 4 or not tuple_date[i].isdigit():
|
||||
test = False
|
||||
break
|
||||
elif len(tuple_date[i]) != 2 or not tuple_date[i].isdigit():
|
||||
test = False
|
||||
break
|
||||
try:
|
||||
parse(answer)
|
||||
except:
|
||||
debug.out(50, "YYYY[-MM-DD]", answer, True, 2, False)
|
||||
ask_domain_date(update)
|
||||
return
|
||||
|
||||
# Exit if not valid
|
||||
if not test:
|
||||
debug.out(50, "YYYY[-MM-DD]", answer, True, 2, True)
|
||||
|
||||
if update: tools.update_ini_file(domain.cf_uri, "DOMAIN", "date", answer)
|
||||
else: return answer
|
||||
|
||||
|
|
|
@ -36,6 +36,9 @@ import os, configparser
|
|||
import domain, debug, tools, tyto
|
||||
|
||||
|
||||
error = 0
|
||||
|
||||
|
||||
#============================================#
|
||||
# Check if current directory is in articles/ #
|
||||
# Check if article from target exists #
|
||||
|
@ -47,20 +50,16 @@ def is_article(target):
|
|||
domain.user_dir.startswith(domain.wrk_articles) or \
|
||||
debug.out(2, "-> articles/", domain.wrk_articles, True, 2, True)
|
||||
|
||||
global error
|
||||
|
||||
# Target URI most be from legacy directory or not begins with
|
||||
if target.startswith(tyto.notarget):
|
||||
debug.out(20, "./, ../", target, True, 2, False)
|
||||
error = 20
|
||||
error = debug.out(20, "./, ../", target, True, 2, False)
|
||||
return False
|
||||
|
||||
# Article exists
|
||||
global uri
|
||||
uri = os.path.join(domain.wrk_articles, target)
|
||||
if not os.path.exists(uri):
|
||||
debug.out(5, "False", uri, True, 2, False)
|
||||
error = 5
|
||||
error = debug.out(5, "False", uri, True, 2, False)
|
||||
return False
|
||||
|
||||
# Article is a Tyto format and not empty (exit on errors)
|
||||
|
@ -89,18 +88,16 @@ def is_article(target):
|
|||
# Return True or False #
|
||||
#-----------------------------------------#
|
||||
def is_tyto_format():
|
||||
global head_contents, text_contents, error
|
||||
global head_contents, text_contents
|
||||
global head_lines, text_lines, lines
|
||||
|
||||
separator = False
|
||||
head_contents = text_contents = ""
|
||||
|
||||
with open(uri, "r") as contents:
|
||||
contents = contents.read()
|
||||
for line in contents.rsplit("\n"):
|
||||
if not line:
|
||||
continue
|
||||
|
||||
if line.startswith(post_sep):
|
||||
for lines, line in enumerate(contents.rsplit("\n"), 1):
|
||||
if line.startswith(sep):
|
||||
separator = True
|
||||
continue
|
||||
|
||||
|
@ -108,20 +105,20 @@ def is_tyto_format():
|
|||
else: head_contents = "%s%s\n"%(head_contents, line)
|
||||
|
||||
if not separator:
|
||||
debug.out(21, post_sep, uri, True, 2, False)
|
||||
error = 21
|
||||
error = debug.out(21, sep, uri, True, 2, False)
|
||||
return False
|
||||
|
||||
if not head_contents:
|
||||
debug.out(22, "?", uri, True, 2, False)
|
||||
error = 22
|
||||
error = debug.out(22, "?", uri, True, 2, False)
|
||||
return False
|
||||
|
||||
if not text_contents:
|
||||
debug.out(23, "?", uri, True, 2, False)
|
||||
error = 23
|
||||
error = debug.out(23, "?", uri, True, 2, False)
|
||||
return False
|
||||
|
||||
head_lines = len(head_contents.rsplit("\n"))
|
||||
text_lines = lines - head_lines
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
@ -156,16 +153,41 @@ def cf_valid():
|
|||
|
||||
|
||||
#======#
|
||||
# MAIN #
|
||||
# MAIN #=======================================================================
|
||||
#======#
|
||||
error = 0
|
||||
|
||||
# Tag separator to split head and text article
|
||||
post_sep = "-----"
|
||||
# head_contents
|
||||
#==============
|
||||
|
||||
# One Line Tags in head article
|
||||
# Optional Tags
|
||||
nositemap = "! NoSitemap" # Article will not be included in sitemap
|
||||
|
||||
# One Line needed
|
||||
sep = "-----" # Splitter between header and article
|
||||
title = ("title:", False)
|
||||
about = ("about:", False)
|
||||
date = ("date:", False)
|
||||
tags = ("tags:", False)
|
||||
author = ("author:", False)
|
||||
|
||||
|
||||
# text_contents
|
||||
# =============
|
||||
# Comments
|
||||
text_comments = (";;", "<!--")
|
||||
html_comment = { text_comments[0] : "<!-- %s -->" }
|
||||
|
||||
# Tyto Titles #1 = <h2>
|
||||
tyto_titles = ("#1", "#2", "#3", "#4", "#5")
|
||||
html_titles = {
|
||||
"#1" : '<h2 class="title_2">%s</h62>',
|
||||
"#2" : '<h3 class="title_3">%s</h3>',
|
||||
"#3" : '<h4 class="title_4">%s</h4>',
|
||||
"#4" : '<h5 class="title_5">%s</h5>',
|
||||
"#5" : '<h6 class="title_6">%s</h6>',
|
||||
}
|
||||
|
||||
# Statistics
|
||||
# ==========
|
||||
stats_comments = 0
|
||||
stats_titles = 0
|
||||
|
|
|
@ -48,35 +48,10 @@ def exit(targets, error):
|
|||
|
||||
#==============================#
|
||||
# Set and return date and time #
|
||||
# With local options from lang #
|
||||
#------------------------------#
|
||||
def nowdate(spec):
|
||||
# Default
|
||||
F_Int = "'%Y-%m-%d %I:%M:%S %p'" # Full International date
|
||||
S_Int = "'%Y-%m-%d" # Short International date
|
||||
|
||||
# Get spec option for local date
|
||||
# Get Used domain lang and set format date
|
||||
locales = ("FLocal", "SLocal")
|
||||
if spec in locales:
|
||||
domain.cf_load()
|
||||
lang = domain.cf.get("WEBSITE", "lang")
|
||||
if lang == "fr":
|
||||
S_Int = "'%d/%m/%Y'"
|
||||
F_Int = "'%d/%m/%Y %H:%M:%S'"
|
||||
|
||||
|
||||
def nowdate():
|
||||
now = datetime.datetime.now()
|
||||
setdate = {
|
||||
"FInt" : now.strftime(F_Int),
|
||||
"SInt" : now.strftime(S_Int),
|
||||
"FLocal" : now.strftime(F_Int),
|
||||
"SLocal" : now.strftime(S_Int),
|
||||
"Year" : now.strftime('%Y'),
|
||||
"Epoch" : int(now.timestamp()),
|
||||
}
|
||||
|
||||
return setdate[spec]
|
||||
return(now.strftime('%Y-%m-%d %H:%M:%S'))
|
||||
|
||||
|
||||
#========================#
|
||||
|
|
Binary file not shown.
|
@ -49,7 +49,7 @@ domain_srv = "URI du serveur"
|
|||
# Errors
|
||||
err_arg = "Argument invalide"
|
||||
err_hole = "Dossier courant invalide"
|
||||
err_date = "Format de date invalide"
|
||||
err_date = "Date invalide"
|
||||
err_lang = "Format de langue invalide"
|
||||
err_dir = "Dossier non compatible"
|
||||
err_no_dir = "Dossier inexistant"
|
||||
|
@ -58,10 +58,11 @@ err_no_file = "Fichier manquant"
|
|||
err_cr_file = "Fichier non créé"
|
||||
err_bad_uri = "URI non compatible"
|
||||
err_post_sep = "Séparateur manquant"
|
||||
err_post_head = "Erreur dans l'Entête"
|
||||
err_post_head = "Entête vide"
|
||||
err_post_empty = "Article vide"
|
||||
err_ini_file = "Configuration invalide"
|
||||
err_post_data = "Article: donnée manquante"
|
||||
err_post_data = "Donnée manquante"
|
||||
err_post_title = "Titre invalide"
|
||||
|
||||
# Warnings
|
||||
warn_no_dom = "Domaine non configuré"
|
||||
|
|
Loading…
Reference in New Issue