Skip to content

Commit

Permalink
Merge pull request #57 from mdrachuk/logging
Browse files Browse the repository at this point in the history
More logging. Rename `include => add`
  • Loading branch information
mdrachuk committed Jun 7, 2020
2 parents 8cb141d + 6ef85fe commit d8e5b5c
Show file tree
Hide file tree
Showing 23 changed files with 223 additions and 166 deletions.
51 changes: 22 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ Code over configuration.
- [x] Jinja2 templates
- [x] Markdown rendering with YAML frontmatter
- [x] Sass/SCSS rendering
- [x] RSS/Atom feeds (basic implementation with ability to pass only plaintext to feeds)
- [x] Site nesting
- [x] Dev server
- [x] Template project
- [x] Clean extensible API
Expand All @@ -32,7 +30,7 @@ pip install lightweight

## Quick Example
```python
from lightweight import Site, markdown, paths, jinja, template, rss, atom, sass
from lightweight import Site, SiteCli, markdown, paths, jinja, template, sass


def blog_posts(source):
Expand All @@ -44,28 +42,30 @@ def example(url):
site = Site(url)

# Render an index page from Jinja2 template.
site.include('index.html', jinja('index.html'))
site.add('index.html', jinja('index.html'))

# Render markdown blog posts.
[site.include(f'blog/{post.source_path.stem}.html', post) for post in blog_posts('posts/**.md')]
site.include('blog.html', jinja('posts.html'))

# Syndicate RSS and Atom feeds.
site.include('blog.atom.xml', atom(site['blog']))
site.include('blog.rss.xml', rss(site['blog']))
[site.add(f'blog/{post.source_path.stem}.html', post) for post in blog_posts('posts/**.md')]
site.add('blog.html', jinja('posts.html'))

# Render SASS to CSS.
site.include('css/global.css', sass('styles/main.scss'))
site.add('css/global.css', sass('styles/main.scss'))

# Include a copy of a directory.
site.include('img')
site.include('js')
site.add('img')
site.add('fonts')
site.add('js')

return site

def generate_prod():
example(url='https://example.org/').generate(out='out')


if __name__ == '__main__':
# Create a site and generate by writing all of it’s content.
example(url='https://example.org/').generate()
# Run CLI with `build` and `serve` commands.
SiteCli(build=example).run()

```

## Create a new project
Expand All @@ -78,41 +78,34 @@ lw init --url https://example.org example
It accepts multiple optional arguments:
```
lw init -h
usage: lw init [-h] --url URL [--title TITLE] location
usage: lw init [-h] [--title TITLE] location
Generate Lightweight skeleton application
positional arguments:
location the directory to initialize site generator in
location the directory to initialize site generator in
optional arguments:
-h, --help show this help message and exit
--url URL the url of the generated site
--title TITLE the title of of the generated site
-h, --help show this help message and exit
--title TITLE the title of of the generated site
```

## Dev Server

Lightweight includes a simple static web server with live reload serving at `localhost:8080`:
```bash
lw serve website:dev
python -m website serve
```
Here `website` is a Python module

Host and port can be changed via:
```bash
lw serve website:dev --host 0.0.0.0 --port 80
```

The directory to resolve the module is provided as `--source`. It defaults to cwd.
The source directory is watched for live reload.
```bash
lw serve website:dev --source ~/Projects/example
python -m website serve --host 0.0.0.0 --port 80
```

The live reload can be disabled with `--no-live-reload` flag:
```bash
lw serve website:dev --no-live-reload
python -m website serve --no-live-reload
```
Otherwise every served HTML file will be injected with a javascript that polls `/__live_reload_id__`.
The script triggers page reload when the value at that location changes.
Expand Down
14 changes: 7 additions & 7 deletions lightweight/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,18 @@ def blog_posts(source):
site = Site(url='https://example.org/')
# Render an index page from Jinja2 template.
site.include('index.html', jinja('pages/index.html'))
site.add('index.html', jinja('pages/index.html'))
# Render markdown blog posts.
[site.include(f'posts/{post.source_path.stem}.html', post) for post in blog_posts('posts/**.md')]
site.include('posts.html', jinja('pages/posts.html'))
[site.add(f'posts/{post.source_path.stem}.html', post) for post in blog_posts('posts/**.md')]
site.add('posts.html', jinja('pages/posts.html'))
# Render SASS to CSS.
site.include('css/style.css', sass('styles/style.scss'))
site.add('css/style.css', sass('styles/style.scss'))
# Include a copy of a directory.
site.include('img')
site.include('js')
site.add('img')
site.add('js')
# Execute all included content.
site.generate()
Expand All @@ -43,4 +43,4 @@ def blog_posts(source):
logger = logging.getLogger('lw')
logger.setLevel(logging.INFO)

__version__ = '1.0.0.dev50'
__version__ = '1.0.0.dev51'
23 changes: 15 additions & 8 deletions lightweight/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def dev(host: str, port: int) -> Site:
from typing import Callable, Any

from .errors import InvalidCommand, InvalidSiteCliUsage
from .lw import start_server, FailedGeneration
from .lw import start_server, FailedGeneration, set_log_level, add_log_arguments
from .site import Site

logger = getLogger('lw')
Expand All @@ -52,11 +52,15 @@ def __init__(
self.default_out = default_out if default_out is not None else Path(getcwd()) / 'out'

def run(self):
args = self._argument_parser().parse_args()
if hasattr(args, 'func'):
args.func(args)
else:
self.help()
try:
args = self._argument_parser().parse_args()
if hasattr(args, 'func'):
set_log_level(args)
args.func(args)
else:
self.help()
except InvalidSiteCliUsage as e:
logger.error(f"{type(e).__name__}: {e}")

def help(self):
self._argument_parser() \
Expand All @@ -72,13 +76,14 @@ def _add_commands(self, subparsers):
self._add_server_cli(subparsers)

def _add_build_cli(self, subparsers):
p = subparsers.add_parser(name='build', description='')
p = subparsers.add_parser(name='build', description='Generate site to the out directory')
p.add_argument('--out', type=str, default=self.default_out,
help='output directory for generation results.Defaults to cwd / "out"')
p.add_argument('--host', type=str, default=None, help=f'defaults to "{self.default_host}"')
p.add_argument('--port', type=int, default=None, help=f'defaults to "{self.default_port}"')
p.add_argument('--url', type=str, default=None,
help=f'defaults to "http://{self.default_host}:{self.default_port}/"')
add_log_arguments(p)
p.set_defaults(func=self._run_build)

def _run_build(self, args: Any):
Expand All @@ -91,6 +96,7 @@ def _run_build(self, args: Any):
host = args.host if args.host is not None else self.default_host
port = args.port if args.port is not None else self.default_port
url = f'http://{host}:{port}/'
logger.info(f' Starting building "{url}"')
self.build(url).generate(args.out)

def _add_server_cli(self, subparsers):
Expand All @@ -107,6 +113,7 @@ def _add_server_cli(self, subparsers):
p.add_argument('--no-live-reload', action='store_true', default=False,
help='disable live reloading '
'(enabled by default calling the executable on every project file change)')
add_log_arguments(p)
if inspect.ismethod(self.build):
raise InvalidSiteCliUsage("SiteCli first argument (<build>) must be a module-level function. "
"It cannot be a method.")
Expand Down Expand Up @@ -145,4 +152,4 @@ def positional_args_count(func: Callable, *, equals: int) -> bool:
"""
count = equals
params = inspect.signature(func).parameters
return len(params) >= count and all(p.default != p.empty for p in list(params.values())[count:])
return len(params) >= count and all(p.default != p.empty for p in list(params.values())[count:])
4 changes: 2 additions & 2 deletions lightweight/content/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from .content_abc import Content
from .copies import copy
from .jinja_doc import jinja, from_ctx
from .md_doc import markdown
from .jinja_page import jinja, from_ctx
from .md_page import markdown
from .sass_scss import sass
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

__all__ = ['JinjaPage', 'jinja', 'from_ctx']

from dataclasses import dataclass
from dataclasses import dataclass, field
from pathlib import Path
from typing import Dict, Any, Union, TYPE_CHECKING, Callable, TypeVar, Generic

Expand All @@ -24,9 +24,9 @@
class JinjaPage(Content):
"""Content rendered from a Jinja Template."""

template: Template
template: Template = field(repr=False)
source_path: Path
props: Dict[str, Any]
props: Dict[str, Any] = field(repr=False)

def write(self, path: GenPath, ctx: GenContext):
path.create(self.render(ctx))
Expand Down Expand Up @@ -84,7 +84,7 @@ def post_tasks(ctx: GenContext):
...
site.include('posts', jinja('posts.html', posts=from_ctx(post_tasks)))
site.add('posts', jinja('posts.html', posts=from_ctx(post_tasks)))
```
"""
return LazyContextParameter(func)
Expand Down
22 changes: 11 additions & 11 deletions lightweight/content/md_doc.py → lightweight/content/md_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
...
site.include('hello.html', markdown('posts/hello.md', template('templates/post.html')))
site.add('hello.html', markdown('posts/hello.md', template('templates/post.html')))
```
[1]: https://daringfireball.net/projects/markdown/
"""
from __future__ import annotations

from dataclasses import dataclass
from dataclasses import dataclass, field
from datetime import datetime, timezone
from pathlib import Path
from typing import Optional, Union, TYPE_CHECKING, Type, Dict, Any
Expand All @@ -23,7 +23,7 @@
from mistune import Markdown # type: ignore

from .content_abc import Content
from .jinja_doc import _eval_if_lazy
from .jinja_page import _eval_if_lazy
from .lwmd import LwRenderer, TableOfContents

if TYPE_CHECKING:
Expand All @@ -36,17 +36,17 @@ class MarkdownPage(Content):

template: Template # Jinja2 template
source_path: Path # path to the markdown file
text: str # the contents of a markdown file
text: str = field(repr=False) # the contents of a markdown file

renderer: Type[LwRenderer]
renderer: Type[LwRenderer] = field(repr=False)

title: Optional[str]
summary: Optional[str]
created: Optional[datetime]
updated: Optional[datetime]
summary: Optional[str] = field(repr=False)
created: Optional[datetime] = field(repr=False)
updated: Optional[datetime] = field(repr=False)

front_matter: Dict[str, Any]
props: Dict[str, Any]
front_matter: Dict[str, Any] = field(repr=False)
props: Dict[str, Any] = field(repr=False)

def write(self, path: GenPath, ctx: GenContext):
"""Writes a rendered Jinja template with rendered Markdown, parameters from front-matter and code
Expand Down Expand Up @@ -102,7 +102,7 @@ def markdown(md_path: Union[str, Path], template: Union[Template], *, renderer=L
Provided key-word arguments are passed as props to the template on render.
Such props can also be lazily evaluated from [GenContext]
by using the [from_ctx(func) decorator][lightweight.content.jinja_doc.from_ctx].
by using the [from_ctx(func) decorator][lightweight.content.jinja_page.from_ctx].
"""
path = Path(md_path)
source = path.read_text(encoding='utf-8')
Expand Down
4 changes: 2 additions & 2 deletions lightweight/content/sass_scss.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
...
site.include('css/style.css', sass('styles/style.scss', sourcemap=False))
site.add('css/style.css', sass('styles/style.scss', sourcemap=False))
```
[1]: https://sass-lang.com
Expand Down Expand Up @@ -78,7 +78,7 @@ def sass(location: str, *, sourcemap: bool = True) -> Sass:
Sourcemaps are written under "<location>.map".
```python
site.include('css/style.css', sass('styles/style.scss'))
site.add('css/style.css', sass('styles/style.scss'))
```
Creates 2 files: `css/styles.css` and `css/styles.css.map`.
"""
Expand Down
2 changes: 1 addition & 1 deletion lightweight/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def directory(location: Union[str, Path]):
project_location = Path(__file__).absolute().parent
with directory(project_location):
site.include('index.html')
site.add('index.html')
```
"""
Expand Down
2 changes: 1 addition & 1 deletion lightweight/generation/path.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
@dataclass(frozen=True)
class GenPath:
"""A path for [writing content][lightweight.content.Content.write].
It contains both, the relative path (as specified by `site.include(relative_path, content)`)
It contains both, the relative path (as specified by `site.add(relative_path, content)`)
and the real path (an absolute path which in site’s `out`).
File system operations performed on real_path; relative path is used for all other operations,
Expand Down
11 changes: 9 additions & 2 deletions lightweight/generation/task.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from dataclasses import dataclass
from logging import getLogger

from lightweight import Content

from .path import GenPath
from .context import GenContext
from .path import GenPath

logger = getLogger('lw')


@dataclass(frozen=True)
Expand All @@ -24,3 +26,8 @@ class GenTask:
ctx: GenContext
content: Content
cwd: str # current working directory

def execute(self):
self.ctx.site.info(f'Writing "{self.path}"')
self.ctx.site.debug(f'{self.path}: CWD={self.cwd} CONTENT={self.content}')
self.content.write(self.path, self.ctx)
Loading

0 comments on commit d8e5b5c

Please sign in to comment.