diff --git a/core/builder/context.py b/core/builder/context.py index 1ad77c53..a3b9eeb6 100644 --- a/core/builder/context.py +++ b/core/builder/context.py @@ -9,7 +9,7 @@ from enschema import Schema, SchemaMissingKeyError, SchemaError, And from typing import Any, Self -from core.utilities import dicts, colour as c, crawler, logger +from core.utilities import colour as c, crawler, logger log = logger.setupLog('dgs') @@ -80,7 +80,11 @@ def adopt(self, **ctxs: 'Context') -> Self: """ Adopt a new child context `ctx` under the key `key` """ for key, ctx in ctxs.items(): assert isinstance(ctx, Context) - self.data[key] = dicts.merge(self.data.get(key), ctx.data) + + if key in self.data: + self.data[key] |= ctx.data + else: + self.data[key] = copy.deepcopy(ctx.data) if self._schema is not None: # If child has no schema, accept anything, otherwise merge diff --git a/core/builder/i18n.py b/core/builder/i18n.py index 68873a91..df8a3c91 100644 --- a/core/builder/i18n.py +++ b/core/builder/i18n.py @@ -14,7 +14,7 @@ def __init__(self, root, language): self.populate(language) def populate(self, language): - self.data = {'i18n': i18n.languages[language].as_dict()} + self._data = {'i18n': i18n.languages[language].as_dict()} self.add_id(language) diff --git a/core/builder/jinja.py b/core/builder/jinja.py index fd166d56..8224306f 100644 --- a/core/builder/jinja.py +++ b/core/builder/jinja.py @@ -4,7 +4,7 @@ import logging from pathlib import Path -from core.utilities import dicts, filters, colour as c +from core.utilities import filters, colour as c log = logging.getLogger('dgs') diff --git a/core/templates/override.jtt b/core/templates/override.jtt index e3356d8f..78af544a 100644 --- a/core/templates/override.jtt +++ b/core/templates/override.jtt @@ -1,5 +1,5 @@ \selectlanguage{(* i18n.name *)} -\setquotestyle[(* i18n.quotes.extra|default('') *)]{(* i18n.quotes.id *)} +\setquotestyle[(* i18n.quotes.extra|default('') *)]{(* i18n.quotes.babel_id *)} \sisetup{ output-decimal-marker = {(* i18n.siunitx.output_decimal_marker *)}, diff --git a/core/utilities/context.py b/core/utilities/context.py deleted file mode 100644 index 834d4fc4..00000000 --- a/core/utilities/context.py +++ /dev/null @@ -1,110 +0,0 @@ -import math -import os -import pprint -import sys -import yaml - -from collections.abc import Iterable - -from core.utilities import dicts, colour as c - - -class Context: - def __init__(self): - self.data = {} - - def add(self, *dictionaries): - """ Merge a list of dictionaries into this context, overriding same keys """ - self.data = dicts.merge(self.data, *dictionaries) - return self - - def absorb(self, key, ctx): - """ Absorb a new context `ctx` under the key `key` """ - self.data[key] = dicts.merge(self.data.get(key), ctx.data) - return self - - def load_yaml(self, *args): - filename = os.path.join(*args) - try: - contents = yaml.load(open(filename, 'r'), Loader=yaml.SafeLoader) - contents = {} if contents is None else contents - except FileNotFoundError: - print(c.err("[FATAL] Could not load YAML file"), c.path(filename)) - sys.exit(43) - - self.data = contents - return self - - def load_meta(self, *args): - return self.load_yaml(self.node_path(*args) / 'meta.yaml') - - def node_path(self, *args): - raise NotImplementedError("Child classes must implement node_path method") - - def print(self): - pprint.pprint(self.data) - - def set_number(self): - return self.add({'number': self.number}) - - def add_number(self, number): - return self.add({'number': number}) - - def set_id(self): - return self.add({'id': self.id}) - - def add_id(self, new_id): - return self.add({'id': new_id}) - - -def is_prime(what: int) -> int: - if not type(what) is int or what < 2: - return 0 - else: - return int(all(what % x != 0 for x in range(2, math.isqrt(what) + 1))) - - -def split_mod(what: Iterable, count: int, first: int = 0) -> list: - result = [[] for _ in range(0, count)] - for i, item in enumerate(what): - result[(i + first) % count].append(item) - return result - - -def split_div(what, count): - return [] if what == [] else [what[0:count]] + split_div(what[count:], count) - - -def split_callback(what, callback, count): - """ - Split `what` by `callback` function, using `count` bins - what: [a] - callback: a -> int, result must be 0 <= result < count - """ - result = [[] for _ in range(0, count)] - for i, item in enumerate(what): - result[callback(i)].append(item) - - return result - - -def add_numbers(what, start=0): - result = [] - num = start - for item in what: - result.append({ - 'number': num, - 'id': item, - }) - num += 1 - return result - - -def numerate(objects, start=0): - num = start - for item in objects: - dicts.merge(item, { - 'number': num - }) - num += 1 - return objects diff --git a/core/utilities/dicts.py b/core/utilities/dicts.py deleted file mode 100644 index 73679b69..00000000 --- a/core/utilities/dicts.py +++ /dev/null @@ -1,26 +0,0 @@ -from typing import Iterable, Dict - - -def merge(parent: Dict, *children: dict, overwrite=True) -> Dict: - for child in children: - parent = merge_one(parent, child) - return parent - - -def merge_one(parent: Dict, child: Dict, *, overwrite=True) -> Dict: - if id(parent) == id(child): - return parent - - if parent is None: - return child - - for key in child: - if key in parent: - if isinstance(parent[key], dict) and isinstance(child[key], dict): - merge_one(parent[key], child[key]) - else: - parent[key] = child[key] - else: - parent[key] = child[key] - - return parent diff --git a/core/utilities/lists.py b/core/utilities/lists.py index 4d21a179..9f3fa8f8 100644 --- a/core/utilities/lists.py +++ b/core/utilities/lists.py @@ -1,10 +1,8 @@ import itertools from typing import Iterable, Callable, List, Dict, Any -from core.utilities import dicts - -def add_numbers(items: List[Any], numbers: Iterable=itertools.count()) -> List[Dict]: +def add_numbers(items: List[Any], numbers: Iterable = itertools.count()) -> List[Dict]: """ Take a list `items` and return a list of dictionaries with number included. @@ -20,7 +18,7 @@ def add_numbers(items: List[Any], numbers: Iterable=itertools.count()) -> List[D List[Dict] A list of dictionaries in format {'number': int, 'id': item} """ - assert type(items) == list + assert isinstance(items, list), f"Cannot add numbers to {type(list)}" result = [] for item in items: @@ -31,12 +29,10 @@ def add_numbers(items: List[Any], numbers: Iterable=itertools.count()) -> List[D return result -def numerate(items: Dict, numbers: Iterable=itertools.count()) -> List[Dict]: +def numerate(items: dict, numbers: Iterable = itertools.count()) -> dict: for item in items: - assert type(item) == dict - dicts.merge(item, { - 'number': next(numbers) - }) + assert isinstance(item, dict) + item |= {'number': next(numbers)} return items diff --git a/modules/naboj/builder/contexts/base.py b/modules/naboj/builder/contexts/base.py index 9e0819f6..d0636721 100644 --- a/modules/naboj/builder/contexts/base.py +++ b/modules/naboj/builder/contexts/base.py @@ -5,7 +5,8 @@ from core.builder import context from core.builder.builder import get_last_commit_hash, get_branch -from core.utilities.schema import valid_language, CommitHash +from core.utilities.schema import valid_language +from core.builder.validator import CommitHash, String class ContextNaboj(context.FileSystemContext): diff --git a/modules/naboj/builder/contexts/hierarchy.py b/modules/naboj/builder/contexts/hierarchy.py index f29eb565..e9c3b731 100644 --- a/modules/naboj/builder/contexts/hierarchy.py +++ b/modules/naboj/builder/contexts/hierarchy.py @@ -6,13 +6,14 @@ from core import i18n from core.utilities import lists -from core.utilities.schema import string, valid_language, valid_language_name +from core.utilities.schema import valid_language, valid_language_name +from core.builder.validator import String from .base import ContextNaboj class ContextCompetition(ContextNaboj): _schema = Schema({ - 'id': string, + 'id': String, 'tearoff': { 'per_page': int, 'height': int, @@ -22,8 +23,8 @@ class ContextCompetition(ContextNaboj): 'inner': int, }, 'organisation': { - 'name': string, - 'address': string, + 'name': String, + 'address': String, }, 'constants': { str: { @@ -33,7 +34,7 @@ class ContextCompetition(ContextNaboj): Optional('siextra'): str, } }, - 'URL': string, + 'URL': String, 'hacks': dict, }) diff --git a/modules/naboj/builder/language.py b/modules/naboj/builder/language.py index 3e0f3d26..f8ef6cc6 100644 --- a/modules/naboj/builder/language.py +++ b/modules/naboj/builder/language.py @@ -21,7 +21,7 @@ def add_arguments(self): super().add_arguments() self.parser.add_argument('language', type=str) - def id(self): + def ident(self): return self.args.competition, self.args.volume, self.args.language def path(self): diff --git a/modules/naboj/module.mk b/modules/naboj/module.mk index 8cfff74b..2514140d 100644 --- a/modules/naboj/module.mk +++ b/modules/naboj/module.mk @@ -146,7 +146,8 @@ build/naboj/%/pdf-prerequisites: \ $$(subst source/,build/,$$(subst .gp,.pdf,$$(wildcard source/naboj/$$*/problems/*/*.gp))) \ $$(subst source/,build/,$$(subst .gp,.pdf,$$(wildcard source/naboj/$$*/problems/*/*/*.gp))) \ $$(wildcard source/naboj/$$*/meta.yaml) \ - $$(subst $$(cdir),,$$(abspath source/naboj/$$*/../meta.yaml)) ; + $$(subst $$(cdir),,$$(abspath source/naboj/$$*/../meta.yaml)) \ + build/core/i18n ; # All problems, solutions and answers for every language, and overall # / @@ -328,8 +329,9 @@ output/naboj/%: \ # All targets for all venues # / -output/naboj/%/venues: \ - $$(foreach dir,$$(subst source/,output/,$$(wildcard source/naboj/$$*/venues/*)), $$(dir)) ; +output/naboj/%/venues: +# $$(subst source/,output/,$$(wildcard source/naboj/$$*/venues/*)) ; + @echo $(subst source/,output/,$(wildcard source/naboj/$*/venues/*)) ; output/naboj/%/all: \ output/naboj/%/languages \ diff --git a/modules/poetry/builder/context.py b/modules/poetry/builder/context.py index cfe04f56..050346e7 100644 --- a/modules/poetry/builder/context.py +++ b/modules/poetry/builder/context.py @@ -4,7 +4,7 @@ sys.path.append('.') -from core.utilities import context +from core.builder import context class ContextPoetry(context.Context): diff --git a/modules/scholar/builder/contexts/buildable.py b/modules/scholar/builder/contexts/buildable.py index 2aac001c..ecc3b2c8 100644 --- a/modules/scholar/builder/contexts/buildable.py +++ b/modules/scholar/builder/contexts/buildable.py @@ -16,6 +16,7 @@ def populate(self, course: str, year: int, issue: int): module=ContextModule('scholar'), course=ContextCourse(self.root, course), year=ContextYear(self.root, course, year), - i18n=ContextI18n(self.root, self.data['course']['language']), issue=self._issue_context_class(self.root, course, year, issue), + ).adopt( + i18n=ContextI18n(self.root, self.data['course']['language']), ) diff --git a/modules/scholar/builder/lecture.py b/modules/scholar/builder/lecture.py index 1df86c30..14b10dd5 100644 --- a/modules/scholar/builder/lecture.py +++ b/modules/scholar/builder/lecture.py @@ -15,7 +15,7 @@ def add_arguments(self): self.parser.add_argument('course', type=str) self.parser.add_argument('lecture', type=str) - def id(self): + def ident(self): return (self.args.course, self.args.lecture) diff --git a/modules/scholar/module.mk b/modules/scholar/module.mk index c8e722f6..5dcd3ebd 100644 --- a/modules/scholar/module.mk +++ b/modules/scholar/module.mk @@ -58,7 +58,8 @@ build/scholar/%/pdf-prerequisites: \ $$(subst source/,build/,$$(subst .svg,.pdf,$$(wildcard source/scholar/$$*/*/*.svg))) \ $$(subst source/,build/,$$(subst .gp,.pdf,$$(wildcard source/scholar/$$*/*.gp))) \ $$(subst source/,build/,$$(subst .gp,.pdf,$$(wildcard source/scholar/$$*/*/*.gp))) \ - source/scholar/$$*/meta.yaml ; + source/scholar/$$*/meta.yaml \ + build/core/i18n ; build/scholar/%/handout: \ $$(subst source/,build/,$$(subst .md,.tex,$$(wildcard source/scholar/$$*/*.md))) \ diff --git a/modules/seminar/module.mk b/modules/seminar/module.mk index 12b8a2a3..dc25325d 100644 --- a/modules/seminar/module.mk +++ b/modules/seminar/module.mk @@ -59,7 +59,8 @@ build/seminar/%/pdf-prerequisites: \ $$(subst source/,build/,$$(subst .svg,.pdf,$$(wildcard source/seminar/$$*/*/*.svg))) \ $$(subst source/,build/,$$(subst .gp,.pdf,$$(wildcard source/seminar/$$*/*/*.gp))) \ $$(wildcard source/seminar/$$*/*/meta.yaml) \ - source/seminar/$$*/meta.yaml ; + source/seminar/$$*/meta.yaml \ + build/core/i18n ; output/seminar/%/html-prerequisites: \ $$(subst source/,output/,$$(wildcard source/seminar/$$*/*/*.jpg)) \ diff --git a/modules/simple/builder/builder.py b/modules/simple/builder/builder.py index 7c285e4f..e1a4a731 100644 --- a/modules/simple/builder/builder.py +++ b/modules/simple/builder/builder.py @@ -14,11 +14,11 @@ def create_argument_parser(self): self.parser.add_argument('year', type=int) self.parser.add_argument('issue', type=int) - def id(self): - return (self.args.course, self.args.year, self.args.issue) + def ident(self): + return self.args.course, self.args.year, self.args.issue def path(self): - return (self.args.course, f'{self.args.year:04d}', self.subdir, f'{self.args.issue:02d}') + return self.args.course, f'{self.args.year:04d}', self.subdir, f'{self.args.issue:02d}' class BuilderSingle(builder.BaseBuilder): diff --git a/modules/simple/builder/context.py b/modules/simple/builder/context.py index 42d07795..d7a53ac3 100644 --- a/modules/simple/builder/context.py +++ b/modules/simple/builder/context.py @@ -3,7 +3,7 @@ sys.path.append('.') -from core.utilities import context +from core.builder import context class ContextScholar(context.Context): @@ -20,21 +20,23 @@ def node_path(self, root, course=None, year=None, target_type=None, issue=None): class ContextScholarBase(ContextScholar): def __init__(self, root, course, year): super().__init__() - self.absorb('module', ContextModule('scholar')) - self.absorb('course', ContextCourse(root, course)) - self.absorb('year', ContextYear(root, course, year)) + self.adopt( + module=ContextModule('scholar'), + course=ContextCourse(root, course), + year=ContextYear(root, course, year), + ) class ContextHomework(ContextScholarBase): def __init__(self, root, course, year, issue): super().__init__(root, course, year) - self.absorb('issue', ContextIssue(root, course, year, 'homework', issue)) + self.adopt(issue=ContextIssue(root, course, year, 'homework', issue)) class ContextHandout(ContextScholarBase): def __init__(self, root, course, year, issue): super().__init__(root, course, year) - self.absorb('issue', ContextIssue(root, course, year, 'handouts', issue)) + self.adopt(issue=ContextIssue(root, course, year, 'handouts', issue)) class ContextModule(ContextScholar): diff --git a/source/naboj/chem b/source/naboj/chem index 33bb31ea..80e20c1c 160000 --- a/source/naboj/chem +++ b/source/naboj/chem @@ -1 +1 @@ -Subproject commit 33bb31eafa586adfcc99b3be508b681a359d82cc +Subproject commit 80e20c1cd28cfc81b33b210d2ddf8bafcee5586b diff --git a/source/naboj/phys b/source/naboj/phys index 538ec1b6..884cd529 160000 --- a/source/naboj/phys +++ b/source/naboj/phys @@ -1 +1 @@ -Subproject commit 538ec1b667e6e2b57f156a1de73c60fd100bd1a8 +Subproject commit 884cd529e63092d821c380564e3978e1aeb6cd5d diff --git a/source/scholar/TA1 b/source/scholar/TA1 index 056f8336..07e8a277 160000 --- a/source/scholar/TA1 +++ b/source/scholar/TA1 @@ -1 +1 @@ -Subproject commit 056f833613134c66fa8fb2ba366106f832cb8d50 +Subproject commit 07e8a2778e6fb30ca414beaf872e27d0608a2bb3 diff --git a/source/scholar/TA2 b/source/scholar/TA2 index b72d1cf7..e188b746 160000 --- a/source/scholar/TA2 +++ b/source/scholar/TA2 @@ -1 +1 @@ -Subproject commit b72d1cf70c0fadc1b6beb85362b57ba688d8df37 +Subproject commit e188b7464bd5682a7643b5e0c1663e6bee8bd4b4