PK {G@-d d scal/__init__.py#!/usr/bin/env python3
# Copyright Louis Paternault 2013-2015
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see . 1
"""Calendar producer"""
VERSION = "0.3.0"
__AUTHOR__ = "Louis Paternault (spalax@gresille.org)"
__COPYRIGHT__ = "(C) 2011-2015 Louis Paternault. GNU GPL 3 or later."
PK YFe^ِ scal/__main__.py#!/usr/bin/env python3
# Copyright Louis Paternault 2011-2015
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see . 1
"""Produce a calendar."""
import logging
import sys
from scal import calendar, errors, options
from scal.template import generate_tex
import scal
LOGGER = logging.getLogger(scal.__name__)
LOGGER.addHandler(logging.StreamHandler())
def main():
"""Main function"""
arguments = options.commandline_parser().parse_args(sys.argv[1:])
try:
inputcalendar = calendar.Calendar(arguments.FILE[0])
except errors.ConfigError as error:
LOGGER.error("Configuration error in file {}: {}".format(
arguments.FILE[0].name,
error,
))
sys.exit(1)
print(generate_tex(inputcalendar, arguments.template, arguments.weeks))
if __name__ == "__main__":
main()
PK [F!0 !0 scal/calendar.py#!/usr/bin/env python3
# Copyright Louis Paternault 2011-2015
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see . 1
"""Configuration file and its representation."""
import datetime
import logging
import re
from scal import errors
LOGGER = logging.getLogger(__name__)
WEEK_CHOICES = ['both', 'none', 'work', 'iso']
def parse_weeks(text):
"""Convert text into the inner representation of week option."""
if text not in WEEK_CHOICES:
raise KeyError(text)
return {
'work': text in ['both', 'work'],
'iso': text in ['both', 'iso'],
}
def is_between(start, middle, end):
"""Return True if `middle` is between `start` and `end`."""
return start <= middle and middle <= end
class Period:
"""A (possibly named) period of time"""
#pylint: disable=too-few-public-methods
start = None
end = None
name = None
def __init__(self, start, end, name=None):
if start > end:
raise errors.ConfigError("Start date is older than end date.")
self.start = start
self.end = end
self.name = name
def __str__(self):
txt = "{} --- {}".format(self.start, self.end)
if self.name:
return "{}: {}".format(txt, self.name)
else:
return txt
def is_in(self, day):
"""Return True iff ``day`` is in this period."""
return is_between(self.start, day, self.end)
RE_DATE_STR = r'((?P\d{{4}})-)?(?P\d{{2}})-(?P\d{{2}})' #pylint: disable=line-too-long
RE_DATE = re.compile(RE_DATE_STR.format(id=""))
RE_FROMTO = re.compile(r'^From *{} *to *{}$'.format(
RE_DATE_STR.format(id='0'),
RE_DATE_STR.format(id='1'),
))
RE_HOLIDAY = re.compile(r'^(?P{})? *(?P{}) *(?P.*)$'.format(
RE_DATE_STR.format(id='0'),
RE_DATE_STR.format(id='1'),
))
RE_AFFECTATION = re.compile(r'^(?P\w*) *= *(?P.*)$')
DEFAULT_CONFIG = {
'lang': 'english',
'papersize': 'a4paper',
}
WEDNESDAY = 3
def date(year, month, day):
"""Return a `datetime.date` object.
The arguments may be anything that can be converted to integers.
"""
return datetime.date(int(year), int(month), int(day))
def last_day_of_month(mydate):
"Return a date corresponding to the last day of the month of the argument."
if mydate.month == 12:
next_month = mydate.replace(mydate.year + 1, 1, 1)
else:
next_month = mydate.replace(mydate.year, mydate.month + 1, 1)
return next_month - datetime.timedelta(days=1)
def weeknumber(day):
"""Return week number."""
return day.isocalendar()[1]
class Calendar:
"""A calendar, that is, a start date, an end date, and holidays."""
def __init__(self, file):
self.start = None
self.end = None
self.holidays = []
self.config = DEFAULT_CONFIG.copy()
linenumber = 0
for line in file:
linenumber += 1
stripped = line.split("#")[0].strip(' \n')
if not stripped:
continue
if RE_FROMTO.match(stripped):
match = RE_FROMTO.match(stripped)
self.set_start(
match.group('year0'),
match.group('month0'),
match.group('day0'),
)
self.set_end(
match.group('year1'),
match.group('month1'),
match.group('day1')
)
elif RE_HOLIDAY.match(stripped):
match = RE_HOLIDAY.match(stripped)
self.add_holiday(
(
match.group('year0'),
match.group('month0'),
match.group('day0'),
),
(
match.group('year1'),
match.group('month1'),
match.group('day1'),
),
match.group('name'),
line
)
elif RE_AFFECTATION.match(stripped):
match = RE_AFFECTATION.match(stripped)
self.config[match.group('name')] = match.group('value')
else:
raise errors.ConfigError(
"Could not parse line {}: '{}'.".format(
linenumber,
line[:-1],
)
)
if self.start is None or self.end is None:
raise errors.ConfigError("Missing start or end date.")
# Filling first and last month
if self.start.day != 1:
self.holidays.append(Period(
datetime.date(self.start.year, self.start.month, 1),
self.start - datetime.timedelta(days=1),
))
self.start = datetime.date(self.start.year, self.start.month, 1)
if self.end != last_day_of_month(self.end):
self.holidays.append(Period(
self.end + datetime.timedelta(days=1),
last_day_of_month(self.end),
))
self.end = last_day_of_month(self.end)
def set_start(self, year, month, day):
"""Defin the start date of the calendar."""
if self.start is not None:
raise errors.ConfigError(
"Calendar boundaries configured twice."
)
if year is None:
raise errors.ConfigError(
"Missing year in 'From to ' line."
)
self.start = date(year, month, day)
def set_end(self, year, month, day):
"""Defin the end date of the calendar."""
if self.end is not None:
raise errors.ConfigError(
"Calendar boundaries configured twice."
)
if year is None:
raise errors.ConfigError(
"Missing year in 'From to ' line."
)
self.end = date(year, month, day)
def add_holiday(self, date0, date1, name="", line=None):
"""Add a holiday, starting on `date0` and ending on `date1`.
This holiday may be named. If it is read from the
configuration file, the content of the corresponding line may
be provided.
"""
year0, month0, day0 = date0
year1, month1, day1 = date1
if (year0 is None) and (month0 is None) and (day0 is None):
year0, month0, day0 = year1, month1, day1
if (
(year0 is None) and (year1 is not None)
) or (
(year0 is not None) and (year1 is None)
):
raise errors.ConfigError(
"Either one or both years may be omitted (line '{}').".format(
str(line)
)
)
if year0 is None:
for year in range(self.start.year, self.end.year + 1):
try:
if (
is_between(
self.start,
date(year, month0, day0),
self.end,
)
and is_between(
self.start,
date(year, month1, day1),
self.end,
)
):
self.holidays.append(Period(
date(year, month0, day0),
date(year, month1, day1),
name,
))
except errors.ConfigError:
LOGGER.warning(
(
"Ignored period {}--{} (invalid or outside "
"calendar boundaries)."
).format(
date(year, month0, day0),
date(year, month1, day1)
)
)
else:
try:
self.holidays.append(Period(
date(year0, month0, day0),
date(year1, month1, day1),
name,
))
except errors.ConfigError:
LOGGER.warning(
(
"Ignored period {}--{} (invalid or outside calendar "
"boundaries)."
).format(
date(year0, month0, day0),
date(year1, month1, day1),
)
)
def is_holiday(self, day):
"""Return True iff ``day`` is in a holiday."""
return len([
None
for holiday
in self.holidays
if holiday.is_in(day)
]) > 0
def months_count(self):
"""Return the number of months of the calendar."""
return (
12 * (self.end.year - self.start.year)
+ self.end.month
- self.start.month
+ 1
)
def year_boundaries(self):
"""Return the first and last month of each year, as a dictionary.
This is important for the first and last years, which can
start or end by something else than January or December.
"""
years = {}
for year in range(self.start.year, self.end.year + 1):
if self.start.year == self.end.year:
boundaries = [self.start.month, self.end.month]
elif year == self.start.year:
boundaries = [self.start.month, 12]
elif year == self.end.year:
boundaries = [1, self.end.month]
else:
boundaries = [1, 12]
years[year] = [format(i, '02d') for i in boundaries]
return years
def is_workingweek(self, wednesday):
"""Return True iff week of argument is a working week."""
all_holiday = True
for day in range(wednesday.toordinal() - 2, wednesday.toordinal() + 3):
all_holiday = (
all_holiday
and self.is_holiday(datetime.date.fromordinal(day))
)
return not all_holiday
def week_iterator(self):
"""Iterate over weeks of self."""
# Looking for first wednesday
for day in range(self.start.toordinal(), self.start.toordinal()+7):
if datetime.date.fromordinal(day).isoweekday() == WEDNESDAY:
wednesday = datetime.date.fromordinal(day)
workweek = 0
while wednesday <= self.end:
if self.is_workingweek(wednesday):
workweek += 1
maybe_workweek = workweek
else:
maybe_workweek = None
yield wednesday, maybe_workweek, weeknumber(wednesday)
wednesday += datetime.timedelta(days=7)
def weeks(self, work, iso):
"""Return the list of weeks, processed by template."""
weeks = []
for (day, work_number, iso_number) in self.week_iterator():
week = {
'date': day,
'work': None,
'iso': None,
}
if work:
week['work'] = work_number
if iso:
week['iso'] = iso_number
weeks.append(week)
return weeks
def __str__(self):
return (
"From {} to {}\n".format(self.start, self.end)
+
"\n".join([str(holiday) for holiday in self.holidays])
)
PK HE%s scal/errors.py#!/usr/bin/env python3
# Copyright Louis Paternault 2011-2014
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see . 1
"""Errors and exceptions"""
class ScalError(Exception):
"""Generic error for scal"""
pass
class ConfigError(ScalError):
"""Error in configuration file."""
def __init__(self, message=""):
super().__init__()
self.message = message
def __str__(self):
return self.message
PK 7TG%*^ ^ scal/options.py#!/usr/bin/env python3
# Copyright Louis Paternault 2011-2015
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see . 1
"""Command line options"""
import argparse
import os
import textwrap
import sys
from scal import VERSION
from scal import calendar
def _type_week(text):
"""Check that --week argument is of the right type."""
try:
return calendar.parse_weeks(text)
except KeyError:
raise argparse.ArgumentTypeError(
"argument must be one of {{{}}}.".format(
", ".join(calendar.WEEK_CHOICES)
)
)
def _file_exists(text):
"""Check that file exists."""
if os.path.exists(text):
return text
else:
raise argparse.ArgumentTypeError(
"'{}' must be an existing file.".format(text)
)
def commandline_parser():
"""Return a command line parser."""
parser = argparse.ArgumentParser(
prog="scal",
description="A year calendar producer.",
)
parser.add_argument(
'--version',
help='Show version',
action='version',
version='%(prog)s ' + VERSION
)
parser.add_argument(
'--weeks', '-w',
help=textwrap.dedent("""
Display week numbers : ISO week numbers, number of worked weeks
since the beginning, or both.
"""),
type=_type_week,
default='both',
)
parser.add_argument(
'--template', '-t',
help='Template to use, if different from default template',
type=_file_exists,
default=None,
metavar="FILE",
)
parser.add_argument(
'FILE',
help='Configuration file',
nargs=1,
type=argparse.FileType('r'),
default=sys.stdin,
)
return parser
PK VF scal/template.py#!/usr/bin/env python3
# Copyright Louis Paternault 2011-2015
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see . 1
"""Calendar generation"""
import jinja2
import os
import pkg_resources
from scal import VERSION
import scal
def generate_tex(calendar, template=None, weeks=None):
"""Generate TeX code producing calendar represented in argument.
:arg Calendar calendar: A :class:`Calendar` object.
:arg str template: The name of a template to use. Use ``None`` for default
template.
"""
if template is None:
basename = "template.tex"
dirname = os.path.dirname(pkg_resources.resource_filename( #pylint: disable=no-member
"scal",
os.path.join("data", "templates", basename)
))
else:
basename = os.path.basename(template)
dirname = os.path.dirname(template)
if weeks is None:
weeks = scal.calendar.parse_weeks("none")
environment = jinja2.Environment(
loader=jinja2.FileSystemLoader(dirname)
)
environment.block_start_string = '(*'
environment.block_end_string = '*)'
environment.variable_start_string = '(('
environment.variable_end_string = '))'
environment.comment_start_string = '(% comment %)'
environment.comment_end_string = '(% endcomment %)'
environment.line_comment_prefix = '%!'
#environment.filters['escape_tex'] = _escape_tex
environment.trim_blocks = True
environment.lstrip_blocks = True
return environment.get_template(basename).render({ #pylint: disable=maybe-no-member
'start': calendar.start,
'end': calendar.end,
'nb_months': calendar.months_count(),
'holidays': calendar.holidays,
'config': calendar.config,
'years': calendar.year_boundaries(),
'weeks': calendar.weeks(weeks['work'], weeks['iso']),
'version': "`scal` version {}".format(VERSION),
})
PK dGX scal/data/templates/template.tex%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Copyright 2012 Robert Krause
% Copyright 2014 Louis Paternault
% License : Creative Commons Attribution License
%
% Produced by ((version)).
% http://git.framasoft.org/spalax/scal
%
% Compile it using `lualatex`
%
% History:
% This file has been posted by original author Robert Krause on TeXample.net
% [1] on 13 July 2012. I (Louis Paternault) used it as a base for this
% template, for the scal software.
%
% [1] http://www.texample.net/tikz/examples/a-calender-for-doublesided-din-a4/
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\documentclass[10pt]{article}
\IfFileExists{hyperref.sty}{
\usepackage[
pdftitle={Calendar for years
(*for year in years|sort*)
((year))
(*endfor*)
},
pdfcreator={LuaLaTeX, using a file generated by ((version))},
]{hyperref}
}{
% Hyperref not loaded
}
\usepackage{fontspec}
\renewcommand{\familydefault}{\sfdefault}
\usepackage[((config.lang))]{babel}
\usepackage[((config.lang))]{translator} % Internationalized Month and Day names
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{calendar}
\usepackage[((config.papersize)), landscape, margin=.5cm]{geometry}
\newcommand{\cellwidth}{\textwidth/((nb_months))}
\newcommand{\cellheight}{\textheight/34}
\newcommand{\cellsep}{2pt}
% Names of Holidays are inserted by employing this macro. Arguments:
% - #1: First day of holidays
% - #2: Holiday name
\def\printholiday#1#2{
\node [anchor=north west, align=right, text width={\cellwidth-\cellsep-7pt}] at
($(cal-#1.north west)$) {\tiny{#2\par}};
}
% Display weeks
% - #1 Day in which week is to be written
% - #2 Week number (as LaTeX code)
\def\printweek#1#2{
\node [anchor=east, align=center, color=gray] at
($(cal-#1.east)$) {{#2\par}};
}
% Display the year. Arguments are:
% - #1: Year
% - #2: First day of year
% - #3: First day of last month of year
\newcommand{\printyear}[3]{
\draw[fill=red!70, draw=none]
($(cal-#1-#2-01.north west)+(0, {2*\cellheight})$)
rectangle
($(cal-#1-#3-01.south east)+(0, {2*\cellheight})$)
node[midway, text=white]{\textbf{#1}};
}
\pagestyle{empty}
\begin{document}
\begin{center}
\begin{tikzpicture}[every day/.style={anchor = north}]
\pgftransformyshift{\cellheight}
\calendar[
dates=((start)) to ((end)),
name=cal,
day yshift = \cellheight,
day code=
{
\node[name=\pgfcalendarsuggestedname,every day,shape=rectangle,
minimum height= \cellheight, draw=black, text width = {\cellwidth-\cellsep-7pt}]{};
\draw ($(\pgfcalendarsuggestedname.west)+(0 em,0)$) node[anchor=west, color=gray]{\tikzdaytext};
\draw ($(\pgfcalendarsuggestedname.west)+(1.5em,0)$) node[anchor=west, color=gray]{\footnotesize \pgfcalendarweekdayshortname{\pgfcalendarcurrentweekday}};
},
execute before day scope=
{
\ifdate{day of month=1}
{
% Shift right
\pgftransformxshift{\cellwidth}
% Print month name
\draw (0,0) node [shape=rectangle, minimum height= \cellheight,
text width = {\cellwidth-\cellsep-7pt}, fill = red!70, text= white, draw = red!70, text centered]
{\textbf{\pgfcalendarmonthname{\pgfcalendarcurrentmonth}}};
}{}
\ifdate{workday}
{
% normal days are white
\tikzset{every day/.style={fill=white}}
% Holidays
(* for holiday in holidays *)
\ifdate{between=((holiday.start)) and ((holiday.end))}{%
\tikzset{every day/.style={fill=gray!30}}}{}
(* endfor *)
}{}
% Saturdays
\ifdate{Saturday}{\tikzset{every day/.style={fill=red!10}}}{}
% Sundays
\ifdate{Sunday}{\tikzset{every day/.style={fill=red!20}}}{}
},
execute at begin day scope=
{
% each day is shifted down according to the day of month
\pgftransformyshift{-{\cellheight * \number\pgfcalendarcurrentday}}
}
];
% Print name of Holidays
(* for holiday in holidays if holiday.name *)
\printholiday{((holiday.start))}{((holiday.name))}
(* endfor *)
% Print week numbers
(* for week in weeks if week.work and week.iso *)
\printweek{((week.date))}{((week.work)) / ((week.iso))}
(* endfor *)
(* for week in weeks if week.iso and not week.work *)
\printweek{((week.date))}{((week.iso))}
(* endfor *)
(* for week in weeks if week.work and not week.iso*)
\printweek{((week.date))}{((week.work))}
(* endfor *)
% Print years
(* for year, boundaries in years.items() *)
\printyear{((year))}{((boundaries[0]))}{((boundaries[1]))}
(* endfor *)
\end{tikzpicture}
\end{center}
\end{document}
PK ۳9Hu< < $ Scal-0.3.0.dist-info/DESCRIPTION.rstscal — School year calendar generator
=====================================
|sources| |pypi| |documentation| |license|
I use this program about once a year to print a one-page school-year
calendar. But it can be used to represent any calendar.
It is heavily inspired by the simple yet powerful Robert Krause's `calendar
`_,
itself using the complex yet powerful Till Tantau's `TikZ
`_ LaTeX package.
Examples:
- French school year:
- 2015-2016:
`zone A `__ (`source `__),
`zone B `__ (`source `__),
`zone C `__ (`source `__)
- 2016-2017:
`zone A `__ (`source `__),
`zone B `__ (`source `__),
`zone C `__ (`source `__)
- 2017-2018:
`zone A `__ (`source `__),
`zone B `__ (`source `__),
`zone C `__ (`source `__)
What's new?
-----------
See `changelog
`_.
Download and install
--------------------
See the end of list for a (quick and dirty) Debian package.
* Non-Python dependencies.
This program produces LuaLaTeX code, but does not compile it. So, LaTeX is not
needed to run this program. However, to compile the generated code, you will
need a working LaTeX installation, with ``lualatex``, and LuaLaTeX packages
`geometry `_,
`babel `_,
`tikz `_,
`fontspec `_,
and `translator` (provided by the `beamer `_ package).
Those are provided by `TeXLive `_ on GNU/Linux,
`MiKTeX `_ on Windows, and `MacTeX
`_ on MacOS.
* From sources:
* Download: https://pypi.python.org/pypi/scal
* Install (in a `virtualenv`, if you do not want to mess with your distribution installation system)::
python3 setup.py install
* From pip::
pip install scal
* Quick and dirty Debian (and Ubuntu?) package
This requires `stdeb `_ to be installed::
python3 setup.py --command-packages=stdeb.command bdist_deb
sudo dpkg -i deb_dist/scal-_all.deb
Documentation
-------------
* The compiled documentation is available on `readthedocs
`_
* To compile it from source, download and run::
cd doc && make html
.. |documentation| image:: http://readthedocs.org/projects/scal/badge
:target: http://scal.readthedocs.org
.. |pypi| image:: https://img.shields.io/pypi/v/scal.svg
:target: http://pypi.python.org/pypi/scal
.. |license| image:: https://img.shields.io/pypi/l/scal.svg
:target: http://www.gnu.org/licenses/gpl-3.0.html
.. |sources| image:: https://img.shields.io/badge/sources-scal-brightgreen.svg
:target: http://git.framasoft.org/spalax/scal
PK ӳ9H_$- - % Scal-0.3.0.dist-info/entry_points.txt[console_scripts]
scal = scal.__main__:main
PK ۳9HI3 s s " Scal-0.3.0.dist-info/metadata.json{"classifiers": ["Development Status :: 5 - Production/Stable", "Environment :: Console", "Intended Audience :: Education", "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Topic :: Software Development :: Code Generators", "Topic :: Text Processing :: Markup :: LaTeX"], "extensions": {"python.commands": {"wrap_console": {"scal": "scal.__main__:main"}}, "python.details": {"contacts": [{"email": "spalax@gresille.org", "name": "Louis Paternault", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "http://git.framasoft.org/spalax/scal"}}, "python.exports": {"console_scripts": {"scal": "scal.__main__:main"}}}, "extras": [], "generator": "bdist_wheel (0.26.0)", "license": "GPLv3 or any later version", "metadata_version": "2.0", "name": "Scal", "run_requires": [{"requires": ["jinja2"]}], "summary": "LaTeX generation of school year calendars", "version": "0.3.0"}PK ӳ9HMYK1 " Scal-0.3.0.dist-info/top_level.txtscal
PK 0QRF2 Scal-0.3.0.dist-info/zip-safe
PK ۳9H}\ \ Scal-0.3.0.dist-info/WHEELWheel-Version: 1.0
Generator: bdist_wheel (0.26.0)
Root-Is-Purelib: true
Tag: py3-none-any
PK ۳9HiE Scal-0.3.0.dist-info/METADATAMetadata-Version: 2.0
Name: Scal
Version: 0.3.0
Summary: LaTeX generation of school year calendars
Home-page: http://git.framasoft.org/spalax/scal
Author: Louis Paternault
Author-email: spalax@gresille.org
License: GPLv3 or any later version
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: Education
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Topic :: Software Development :: Code Generators
Classifier: Topic :: Text Processing :: Markup :: LaTeX
Requires-Dist: jinja2
scal — School year calendar generator
=====================================
|sources| |pypi| |documentation| |license|
I use this program about once a year to print a one-page school-year
calendar. But it can be used to represent any calendar.
It is heavily inspired by the simple yet powerful Robert Krause's `calendar
`_,
itself using the complex yet powerful Till Tantau's `TikZ
`_ LaTeX package.
Examples:
- French school year:
- 2015-2016:
`zone A `__ (`source `__),
`zone B `__ (`source `__),
`zone C `__ (`source `__)
- 2016-2017:
`zone A `__ (`source `__),
`zone B `__ (`source `__),
`zone C `__ (`source `__)
- 2017-2018:
`zone A `__ (`source `__),
`zone B `__ (`source `__),
`zone C `__ (`source `__)
What's new?
-----------
See `changelog
`_.
Download and install
--------------------
See the end of list for a (quick and dirty) Debian package.
* Non-Python dependencies.
This program produces LuaLaTeX code, but does not compile it. So, LaTeX is not
needed to run this program. However, to compile the generated code, you will
need a working LaTeX installation, with ``lualatex``, and LuaLaTeX packages
`geometry `_,
`babel `_,
`tikz `_,
`fontspec `_,
and `translator` (provided by the `beamer `_ package).
Those are provided by `TeXLive `_ on GNU/Linux,
`MiKTeX `_ on Windows, and `MacTeX
`_ on MacOS.
* From sources:
* Download: https://pypi.python.org/pypi/scal
* Install (in a `virtualenv`, if you do not want to mess with your distribution installation system)::
python3 setup.py install
* From pip::
pip install scal
* Quick and dirty Debian (and Ubuntu?) package
This requires `stdeb `_ to be installed::
python3 setup.py --command-packages=stdeb.command bdist_deb
sudo dpkg -i deb_dist/scal-_all.deb
Documentation
-------------
* The compiled documentation is available on `readthedocs
`_
* To compile it from source, download and run::
cd doc && make html
.. |documentation| image:: http://readthedocs.org/projects/scal/badge
:target: http://scal.readthedocs.org
.. |pypi| image:: https://img.shields.io/pypi/v/scal.svg
:target: http://pypi.python.org/pypi/scal
.. |license| image:: https://img.shields.io/pypi/l/scal.svg
:target: http://www.gnu.org/licenses/gpl-3.0.html
.. |sources| image:: https://img.shields.io/badge/sources-scal-brightgreen.svg
:target: http://git.framasoft.org/spalax/scal
PK ۳9H Scal-0.3.0.dist-info/RECORDScal-0.3.0.dist-info/DESCRIPTION.rst,sha256=G5RuDLS7jI-nWOri27wXIIrf_2vAeBkeKsTYdY-TS5k,4156
Scal-0.3.0.dist-info/METADATA,sha256=6z-VJtonUUFec5xz9pTdAIjaOTa3jPPUQxrSYxLJABU,5015
Scal-0.3.0.dist-info/RECORD,,
Scal-0.3.0.dist-info/WHEEL,sha256=zX7PHtH_7K-lEzyK75et0UBa3Bj8egCBMXe1M4gc6SU,92
Scal-0.3.0.dist-info/entry_points.txt,sha256=aqTT-6E1UtyxBMetV21naj3bfe37F48lNYTOPn4r3-s,45
Scal-0.3.0.dist-info/metadata.json,sha256=G_9MSOxyd2C9HqFZ97xKT61fblcDC_e75qxog-GUHbs,1139
Scal-0.3.0.dist-info/top_level.txt,sha256=98Q5Yy5i_uAZgFae2J9-UD_Ib2jhcVvKPm67Vqqa8r0,5
Scal-0.3.0.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
scal/__init__.py,sha256=MvGsGidqBacAwnUOLCDKlDCY7OlZ4mZSFbjZ0K876ds,868
scal/__main__.py,sha256=KP1UStds-AgnCj1Jf7rsc_fJYj6a0X2AcM6VwYNnRDc,1424
scal/calendar.py,sha256=DMq8c2k24icJ9cqSS-tDwMV30TSHEn-Z5FUtbaMp-I8,12321
scal/errors.py,sha256=qo6OqSEYSwwbKJEvr3AMGp4FBXqkf0aQeUlUJmAOZTA,1015
scal/options.py,sha256=M0HEjSuGogoqKQmZONV3Q9E3uq0Cw-9_GhIovySCY_U,2398
scal/template.py,sha256=ztmYjydSX-gcWieNHUmxOHxfS0SdLsUrwOpcS00tEcw,2493
scal/data/templates/template.tex,sha256=tNcWkolhWb1MyGkzoefmHN4mFJBwdhqzDTbUJrvVcjw,4601
PK {G@-d d scal/__init__.pyPK YFe^ِ scal/__main__.pyPK [F!0 !0 P scal/calendar.pyPK HE%s 9 scal/errors.pyPK 7TG%*^ ^ = scal/options.pyPK VF MG scal/template.pyPK dGX 8Q scal/data/templates/template.texPK ۳9Hu< < $ oc Scal-0.3.0.dist-info/DESCRIPTION.rstPK ӳ9H_$- - % s Scal-0.3.0.dist-info/entry_points.txtPK ۳9HI3 s s " ]t Scal-0.3.0.dist-info/metadata.jsonPK ӳ9HMYK1 " y Scal-0.3.0.dist-info/top_level.txtPK 0QRF2 Uy Scal-0.3.0.dist-info/zip-safePK ۳9H}\ \ y Scal-0.3.0.dist-info/WHEELPK ۳9HiE %z Scal-0.3.0.dist-info/METADATAPK ۳9H Scal-0.3.0.dist-info/RECORDPK + ϒ