[1.9.13]: see changelog

This commit is contained in:
Cyrille L 2023-10-01 01:47:27 +02:00
parent fed0227968
commit 171de8808c
15 changed files with 164 additions and 114 deletions

View File

@ -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

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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'))
#========================#

View File

@ -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é"