def test_types(self): """ YAML doesn't always give us the types we want. Handle that correctly. """ # Yaml will only make something a datetime if it also includes a time. inp = {'datetime': date(2011, 12, 25)} out = { 'datetime': datetime(2011, 12, 25), 'date': date(2011, 12, 25), 'time': time(), } util.date_and_times(inp) self.assertEquals(inp, out) # Yaml likes to give times as the number of seconds. inp = {'date': self.date, 'time': 43200} out = { 'datetime': datetime(2011, 10, 12, 12, 0, 0), 'date': self.date, 'time': time(12, 0, 0), } util.date_and_times(inp) self.assertEquals(inp, out)
def test_date_and_times(self): inp = {'date': self.date, 'time': self.time} out = { 'datetime': datetime(2011, 10, 12, 3, 14, 15, 0), 'date': self.date, 'time': self.time, } util.date_and_times(inp) self.assertEquals(inp, out)
def test_just_date(self): inp = {'date': self.date} out = { 'datetime': datetime(2011, 10, 12, 0, 0, 0, 0), 'date': self.date, 'time': time(), # time() == datetime.time(0, 0) } util.date_and_times(inp) self.assertEquals(inp, out)
def test_blanks(self): inp = {} out = { 'datetime': datetime(1970, 1, 1), 'date': date(1970, 1, 1), 'time': time(), # time == datetime.time(0, 0) } util.date_and_times(inp) self.assertEquals(inp, out)
def test_just_datetime(self): inp = {'datetime': self.datetime} out = { 'datetime': self.datetime, 'date': self.datetime.date(), 'time': self.datetime.time(), } util.date_and_times(inp) self.assertEquals(inp, out)
def test_just_time(self): inp = {'time': self.time} out = { 'datetime': datetime(1970, 1, 1), 'date': date(1970, 1, 1), 'time': self.time, } util.date_and_times(inp) self.assertEquals(inp, out)
def test_just_time(self): t = self.time # otherwise the datetime line gets awful inp = {'time': t} out = { 'datetime': datetime(1970, 1, 1, t.hour, t.minute, t.second), 'date': date(1970, 1, 1), 'time': t, } util.date_and_times(inp) self.assertEquals(inp, out)
def build_meta(self): """ Ensures the guarantees about metadata for documents are valid. `page.title` - Will be a string. `page.slug` - Will be a string. `page.author` - Will have fields `name` and `email`. `page.authors` - Will be a list of Authors. `page.category` - Will be a list. `page.published` - Will exist. `page.datetime` - Will be a datetime, or None. `page.date` - Will be a date, or None. `page.time` - Will be a time, or None. `page.tags` - Will be a list. `page.url` - Will be the url of the page, relative to the web root. `page.subpages` - Will be a list containing every sub page of this page """ self.engine.run_hook('page.meta.pre', self) if not self.meta: self.meta = {} # title if not 'title' in self.meta: if self.filename: # Take off the last file extension. self.meta['title'] = '.'.join(self.filename.split('.')[:-1]) if (self.meta['title'] == ''): self.meta['title'] = self.filename logging.warning("You didn't specify a title in {0}. Using the " "file name as a title.".format(self.path)) elif 'slug' in self.meta: self.meta['title'] = self.meta['slug'] logging.warning("You didn't specify a title in {0}, which was " "not generated from a file. Using the slug as a title." .format(self.meta['slug'])) else: logging.error("A page was generated that is not from a file, " "has no title, and no slug. I don't know what to do. " "Not using this page.") logging.info("Bad Meta's keys: {0}".format(self.meta.keys())) logging.debug("Bad Meta: {0}".format(self.meta)) raise BadMetaException() # slug if not 'slug' in self.meta: if self.filename: filename_no_ext = '.'.join(self.filename.split('.')[:-1]) if filename_no_ext == '': filename_no_ext = self.filename self.meta['slug'] = slugify(filename_no_ext) logging.info("You didn't specify a slug, generating it from the " "filename.") else: self.meta['slug'] = slugify(self.meta['title']) logging.info("You didn't specify a slug, and no filename " "exists. Generating the slug from the title.") elif self.meta['slug'] != slugify(self.meta['slug']): logging.warning('Your slug should probably be all lower case, and ' 'match "[a-z0-9-]*"') # authors and author authors = self.meta.get('authors', self.meta.get('author', None)) if isinstance(authors, list): self.meta['authors'] = [Author.parse(a) for a in authors] elif isinstance(authors, str): self.meta['authors'] = [Author.parse(a) for a in authors.split(',')] if len(self.meta['authors']) > 1: logging.warn('Deprecation Warning: Use YAML lists instead of ' 'CSV for multiple authors. i.e. ["John Doe", "Jane ' 'Smith"] instead of "John Doe, Jane Smith". In ' '{0}.'.format(self.path)) elif authors is None: self.meta['authors'] = self.options.get('authors', []) else: # wait, what? Authors is of wrong type. self.meta['authors'] = [] logging.error(('Authors in {0} is an unknown type. Valid types ' 'are string or list. Instead it is a {1}') .format(self.meta['slug']), authors.type) if self.meta['authors']: self.meta['author'] = self.meta['authors'][0] else: self.meta['author'] = Author() # category if 'category' in self.meta: if isinstance(self.meta['category'], str): self.meta['category'] = self.meta['category'].split('/') elif isinstance(self.meta['category'], list): pass else: # category is of wrong type. logging.error('Category in {0} is an unknown type. Valid ' 'types are string or list. Instead it is a {1}' .format(self.meta['slug'], type(self.meta['category']))) self.meta['category'] = [] else: self.meta['category'] = [] if self.meta['category'] == None: self.meta = [] # published if not 'published' in self.meta: self.meta['published'] = True # make_file if not 'make_file' in self.meta: self.meta['make_file'] = True # datetime, date, time util.date_and_times(self.meta) # tags if 'tags' in self.meta: if isinstance(self.meta['tags'], list): # good pass elif isinstance(self.meta['tags'], str): self.meta['tags'] = [t.strip() for t in self.meta['tags'].split(',')] if len(self.meta['tags']) > 1: logging.warn('Deprecation Warning: Use YAML lists instead ' 'of CSV for multiple tags. i.e. tags: [guide, ' 'howto] instead of tags: guide, howto. In {0}.' .format(self.path)) else: self.meta['tags'] = [] logging.debug('Tags for {0}: {1}'. format(self.meta['slug'], self.meta['tags'])) # pagination if 'pagination' not in self.meta: self.meta['pagination'] = {} if 'cur_page' not in self.meta['pagination']: self.meta['pagination']['cur_page'] = 1 if 'num_pages' not in self.meta['pagination']: self.meta['pagination']['num_pages'] = 1 # template try: template_type = str(self.meta.get('type', 'default')) self.template = self.tmpl_env.get_template(template_type + '.*') except jinja2.loaders.TemplateNotFound: logging.error('No template "{0}.*" found in template directory. Aborting.' .format(template_type)) sys.exit() except AmbiguousTemplate: logging.error(('Ambiguous template found. There are two files that ' 'match "{0}.*". Aborting.').format(template_type)) sys.exit() # url parts = { 'slug': self.meta['slug'], 'category': '/'.join(self.meta['category']), 'page': self.meta['pagination']['cur_page'], 'date': self.meta['date'], 'datetime': self.meta['datetime'], 'time': self.meta['time'], } logging.debug('current page: ' + repr(parts['page'])) # Pull extensions from the template's real file name. parts['ext'] = os.path.splitext(self.template.filename)[1] if parts['ext']: parts['ext'] = parts['ext'][1:] # remove leading dot # Deprecated parts['type'] = parts['ext'] self.meta['ext'] = parts['ext'] if parts['page'] == 1: parts['page'] = '' if 'url' in self.meta: logging.debug('Using page url pattern') self.url_pattern = self.meta['url'] else: logging.debug('Using global url pattern') self.url_pattern = self.options['url_pattern'] self.meta['url'] = self.url_pattern.format(**parts) logging.info('URL pattern is: {0}'.format(self.url_pattern)) logging.info('URL parts are: {0}'.format(parts)) # Get rid of extra slashes self.meta['url'] = re.sub(r'//+', '/', self.meta['url']) # If we have been asked to, rip out any plain "index.html"s if not self.options['url_include_index']: self.meta['url'] = re.sub(r'/index\.html$', '/', self.meta['url']) # To be used for writing page content self.meta['path'] = self.meta['url'] # If site is going to be in a subdirectory if self.options.get('url_subdir'): self.meta['url'] = self.options['url_subdir'] + self.meta['url'] # Some urls should start with /, some should not. if self.options['relative_urls'] and self.meta['url'][0] == '/': self.meta['url'] = self.meta['url'][1:] if not self.options['relative_urls'] and self.meta['url'][0] != '/': self.meta['url'] = '/' + self.meta['url'] logging.debug('url is: ' + self.meta['url']) # subpages self.meta['subpages'] = [] self.engine.run_hook('page.meta.post', self)
def build_meta(self): """ Ensures the guarantees about metadata for documents are valid. `page.title` - Will be a string. `page.slug` - Will be a string. `page.author` - Will have fields `name` and `email`. `page.authors` - Will be a list of Authors. `page.category` - Will be a list. `page.published` - Will exist. `page.datetime` - Will be a datetime, or None. `page.date` - Will be a date, or None. `page.time` - Will be a time, or None. `page.tags` - Will be a list. `page.url` - Will be the url of the page, relative to the web root. `page.subpages` - Will be a list containing every sub page of this page """ if not self.meta: self.meta = {} # title if not 'title' in self.meta: self.meta['title'] = '.'.join(self.filename.split('.')[:-1]) if (self.meta['title'] == ''): self.meta['title'] = self.filename logging.info("You didn't specify a title in {0}. " "Using the file name as a title.".format(self.filename)) # slug if not 'slug' in self.meta: self.meta['slug'] = util.slugify(self.meta['title']) logging.debug("You didn't specify a slug, generating it from the title.") elif self.meta['slug'] != util.slugify(self.meta['slug']): logging.warning('Your slug should probably be all lower case, and ' 'match "[a-z0-9-]*"') # authors and author authors = self.meta.get('authors', self.meta.get('author', None)) if isinstance(authors, list): self.meta['authors'] = [Author.parse(a) for a in authors] elif isinstance(authors, str): self.meta['authors'] = [Author.parse(a) for a in authors.split(',')] if len(self.meta['authors']) > 1: logging.warn('Deprecation Warning: Use YAML lists instead of ' 'CSV for multiple authors. i.e. ["John Doe", "Jane ' 'Smith"] instead of "John Doe, Jane Smith". In ' '{0}.'.format(self.path)) elif authors is None: if 'authors' in self.options: self.meta['authors'] = self.options['authors'] else: self.meta['authors'] = [] else: # wait, what? self.meta['authors'] = [] logging.error(('Authors in {0} is an unknown type. Valid types ' 'are string or list.').format(self.path)) if self.meta['authors']: self.meta['author'] = self.meta['authors'] else: self.meta['author'] = Author() # category if 'category' in self.meta: self.meta['category'] = self.meta['category'].split('/') else: self.meta['category'] = [] if self.meta['category'] == None: self.meta = [] # published if not 'published' in self.meta: self.meta['published'] = True # make_file if not 'make_file' in self.meta: self.meta['make_file'] = True # datetime, date, time util.date_and_times(self.meta) # tags if 'tags' in self.meta: if isinstance(self.meta['tags'], list): # good pass elif isinstance(self.meta['tags'], str): self.meta['tags'] = [t.strip() for t in self.meta['tags'].split(',')] if len(self.meta['tags']) > 1: logging.warn('Deprecation Warning: Use YAML lists instead ' 'of CSV for multiple tags. i.e. tags: [guide, ' 'howto] instead of tags: guide, howto. In {0}.' .format(self.path)) else: self.meta['tags'] = [] logging.debug('Tags for {0}: {1}'. format(self.meta['slug'], self.meta['tags'])) # pagination if 'pagination' not in self.meta: self.meta['pagination'] = {} if 'cur_page' not in self.meta['pagination']: self.meta['pagination']['cur_page'] = 1 if 'num_pages' not in self.meta['pagination']: self.meta['pagination']['num_pages'] = 1 # template try: template_type = self.meta.get('type', 'default') self.template = Page.tmpl_env.get_template(template_type + '.*') except jinja2.loaders.TemplateNotFound: logging.error('No template "{0}.*" found in template directory. Aborting.' .format(template_type)) sys.exit() except AmbiguousTemplate: logging.error(('Ambiguous template found. There are two files that ' 'match "{0}.*". Aborting.').format(template_type)) sys.exit() # url parts = { 'slug': self.meta['slug'], 'category': '/'.join(self.meta['category']), 'page': self.meta['pagination']['cur_page'], } logging.debug('current page: ' + repr(parts['page'])) # Pull extensions from the template's real file name. match = re.match('.*/[^\.]*\.(.*)$', self.template.filename) if match: parts['ext'] = match.groups()[0] else: parts['ext'] = '' # Deprecated parts['type'] = parts['ext'] self.meta['ext'] = parts['ext'] if parts['page'] == 1: parts['page'] = '' if not 'url' in self.meta: self.meta['url'] = self.options['url_pattern'].format(**parts); else: self.meta['url'] = self.meta['url'].format(**parts); # Get rid of extra slashes self.meta['url'] = re.sub(r'//+', '/', self.meta['url']) logging.debug(self.meta['url']) # If we have been asked to, rip out any plain "index.html"s if not self.options['url_include_index']: self.meta['url'] = re.sub(r'/index\.html$', '/', self.meta['url']) # subpages self.meta['subpages'] = []
def test_blanks(self): inp = {} out = {'datetime': None, 'date': None, 'time': None, } util.date_and_times(inp) self.assertEquals(inp, out)
def build_meta(self): """ Ensures the guarantees about metadata for documents are valid. `page.title` - Will be a string. `page.slug` - Will be a string. `page.author` - Will have fields `name` and `email`. `page.authors` - Will be a list of Authors. `page.category` - Will be a list. `page.published` - Will exist. `page.datetime` - Will be a datetime, or None. `page.date` - Will be a date, or None. `page.time` - Will be a time, or None. `page.tags` - Will be a list. `page.url` - Will be the url of the page, relative to the web root. `page.subpages` - Will be a list containing every sub page of this page """ self.engine.run_hook("page.meta.pre", self) if not self.meta: self.meta = {} # title if not "title" in self.meta: if self.filename: # Take off the last file extension. self.meta["title"] = ".".join(self.filename.split(".")[:-1]) if self.meta["title"] == "": self.meta["title"] = self.filename logging.warning( "You didn't specify a title in {0}. Using the " "file name as a title.".format(self.path) ) elif "slug" in self.meta: self.meta["title"] = self.meta["slug"] logging.warning( "You didn't specify a title in {0}, which was " "not generated from a file. Using the slug as a title.".format(self.meta["slug"]) ) else: logging.error( "A page was generated that is not from a file, " "has no title, and no slug. I don't know what to do. " "Not using this page." ) logging.info("Bad Meta's keys: {0}".format(self.meta.keys())) logging.debug("Bad Meta: {0}".format(self.meta)) raise BadMetaException() # slug if not "slug" in self.meta: if self.filename and self.options["slug_from_filename"]: filename_no_ext = ".".join(self.filename.split(".")[:-1]) if filename_no_ext == "": filename_no_ext = self.filename self.meta["slug"] = slugify(filename_no_ext) logging.info("You didn't specify a slug, generating it from the " "filename.") else: self.meta["slug"] = slugify(unicode(self.meta["title"])) logging.info( "You didn't specify a slug, and no filename " "exists. Generating the slug from the title." ) elif self.meta["slug"] != slugify(self.meta["slug"]): logging.warning("Your slug should probably be all lower case, and " 'match "[a-z0-9-]*"') # authors and author authors = self.meta.get("authors", self.meta.get("author", None)) if isinstance(authors, list): self.meta["authors"] = [Author.parse(a) for a in authors] elif isinstance(authors, str): self.meta["authors"] = [Author.parse(a) for a in authors.split(",")] if len(self.meta["authors"]) > 1: logging.warn( "Deprecation Warning: Use YAML lists instead of " 'CSV for multiple authors. i.e. ["John Doe", "Jane ' 'Smith"] instead of "John Doe, Jane Smith". In ' "{0}.".format(self.path) ) elif authors is None: self.meta["authors"] = self.options.get("authors", []) else: # wait, what? Authors is of wrong type. self.meta["authors"] = [] logging.error( ("Authors in {0} is an unknown type. Valid types " "are string or list. Instead it is a {1}").format( self.meta["slug"] ), authors.type, ) if self.meta["authors"]: self.meta["author"] = self.meta["authors"][0] else: self.meta["author"] = Author() # category if "category" in self.meta: if isinstance(self.meta["category"], str): self.meta["category"] = self.meta["category"].split("/") elif isinstance(self.meta["category"], list): pass else: # category is of wrong type. logging.error( "Category in {0} is an unknown type. Valid " "types are string or list. Instead it is a {1}".format( self.meta["slug"], type(self.meta["category"]) ) ) self.meta["category"] = [] else: self.meta["category"] = [] if self.meta["category"] == None: self.meta = [] # published if not "published" in self.meta: self.meta["published"] = True # make_file if not "make_file" in self.meta: self.meta["make_file"] = True # datetime, date, time util.date_and_times(self.meta) # tags if "tags" in self.meta: if isinstance(self.meta["tags"], list): # good pass elif isinstance(self.meta["tags"], str): self.meta["tags"] = [t.strip() for t in self.meta["tags"].split(",")] if len(self.meta["tags"]) > 1: logging.warn( "Deprecation Warning: Use YAML lists instead " "of CSV for multiple tags. i.e. tags: [guide, " "howto] instead of tags: guide, howto. In {0}.".format(self.path) ) else: self.meta["tags"] = [] logging.debug("Tags for {0}: {1}".format(self.meta["slug"], self.meta["tags"])) # pagination if "pagination" not in self.meta: self.meta["pagination"] = {} if "cur_page" not in self.meta["pagination"]: self.meta["pagination"]["cur_page"] = 1 if "num_pages" not in self.meta["pagination"]: self.meta["pagination"]["num_pages"] = 1 # template try: template_type = str(self.meta.get("type", "default")) self.template = self.tmpl_env.get_template(template_type + ".*") except jinja2.loaders.TemplateNotFound: logging.error('No template "{0}.*" found in template directory. Aborting.'.format(template_type)) sys.exit() except AmbiguousTemplate: logging.error( ("Ambiguous template found. There are two files that " 'match "{0}.*". Aborting.').format(template_type) ) sys.exit() # url parts = { "slug": self.meta["slug"], "category": "/".join(self.meta["category"]), "page": self.meta["pagination"]["cur_page"], "date": self.meta["date"], "datetime": self.meta["datetime"], "time": self.meta["time"], } logging.debug("current page: " + repr(parts["page"])) # Pull extensions from the template's real file name. parts["ext"] = os.path.splitext(self.template.filename)[1] if parts["ext"]: parts["ext"] = parts["ext"][1:] # remove leading dot # Deprecated parts["type"] = parts["ext"] self.meta["ext"] = parts["ext"] if parts["page"] == 1: parts["page"] = "" if "url" in self.meta: logging.debug("Using page url pattern") self.url_pattern = self.meta["url"] else: logging.debug("Using global url pattern") self.url_pattern = self.options["url_pattern"] self.meta["url"] = self.url_pattern.format(**parts) logging.info("URL pattern is: {0}".format(self.url_pattern)) logging.info("URL parts are: {0}".format(parts)) # Get rid of extra slashes self.meta["url"] = re.sub(r"//+", "/", self.meta["url"]) # If we have been asked to, rip out any plain "index.html"s if not self.options["url_include_index"]: self.meta["url"] = re.sub(r"/index\.html$", "/", self.meta["url"]) # To be used for writing page content self.meta["path"] = self.meta["url"] # If site is going to be in a subdirectory if self.options.get("url_subdir"): self.meta["url"] = self.options["url_subdir"] + self.meta["url"] # Some urls should start with /, some should not. if self.options["relative_urls"] and self.meta["url"][0] == "/": self.meta["url"] = self.meta["url"][1:] if not self.options["relative_urls"] and self.meta["url"][0] != "/": self.meta["url"] = "/" + self.meta["url"] logging.debug("url is: " + self.meta["url"]) # subpages self.meta["subpages"] = [] self.engine.run_hook("page.meta.post", self)