Skip to content

Commit

Permalink
Added documentation and types for prolog and examples packages (#184)
Browse files Browse the repository at this point in the history
Added documentation and types for prolog and examples packages
  • Loading branch information
yuce authored Oct 20, 2024
1 parent 2403dca commit 1f06e6a
Show file tree
Hide file tree
Showing 14 changed files with 346 additions and 76 deletions.
4 changes: 3 additions & 1 deletion .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ version: 2

# Set the OS, Python version and other tools you might need
build:
os: ubuntu-22.04
os: ubuntu-24.04
tools:
python: "3.12"
apt_packages:
- swi-prolog-nox

# Build documentation in the "docs/" directory with Sphinx
sphinx:
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.PHONY: build clean coverage upload-coverage test upload

build:
build
pyproject-build

clean:
rm -rf dist build pyswip.egg-info
Expand Down
3 changes: 2 additions & 1 deletion dev-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ ruff==0.6.2
build
pytest-cov
mypy>=1.0.0
Sphinx
Sphinx
sphinx-autodoc-typehints
11 changes: 11 additions & 0 deletions docs/source/api/examples.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Examples
--------

.. automodule:: pyswip.examples
:members:

Sudoku
^^^^^^

.. automodule:: pyswip.examples.sudoku
:members:
10 changes: 10 additions & 0 deletions docs/source/api/modules.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
API Documentation
-----------------

.. toctree::

examples
prolog



5 changes: 5 additions & 0 deletions docs/source/api/prolog.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Prolog
------

.. automodule:: pyswip.prolog
:members:
17 changes: 16 additions & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,18 @@
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information

import sys
from pathlib import Path

sys.path.insert(0, str(Path("..", "..", "src").resolve()))

from pyswip import __VERSION__

project = "PySwip"
copyright = "2024, Yüce Tekol and PySwip Contributors"
author = "Yüce Tekol and PySwip Contributors"
version = __VERSION__
release = version

# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
Expand All @@ -17,6 +26,7 @@
"sphinx.ext.duration",
"sphinx.ext.doctest",
"sphinx.ext.autodoc",
"sphinx_autodoc_typehints",
]

templates_path = ["_templates"]
Expand All @@ -26,11 +36,16 @@
# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output

html_theme = "alabaster"
html_theme = "bizstyle"
html_static_path = ["_static"]

source_suffix = {
".rst": "restructuredtext",
".txt": "markdown",
".md": "markdown",
}

autodoc_member_order = "bysource"
autoclass_content = "both"

html_logo = "https://pyswip.org/images/pyswip_logo_sm_256colors.gif"
9 changes: 9 additions & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,13 @@ It features an SWI-Prolog foreign language interface, a utility class that makes
:caption: Contents:

get_started
api/modules

Indices and Tables
==================

.. toctree::

genindex
modindex

10 changes: 8 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ keywords = [
"prolog",
]
classifiers = [
"Development Status :: 3 - Alpha",
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: MIT License",
Expand All @@ -45,4 +45,10 @@ ignore = ["F403", "F405", "E721"]
[tool.pytest.ini_options]
markers = [
"slow: marks tests as slow (deselect with '-m \"not slow\"')",
]
]

[tool.setuptools.package-data]
"pyswip" = ["py.typed"]

[tool.setuptools.packages.find]
where = ["src"]
104 changes: 90 additions & 14 deletions src/pyswip/examples/sudoku.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,20 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

import sys
from typing import List, Union, Literal
"""
Sudoku example
You can run this module using::
$ python3 -m pyswip.examples.sudoku
"""

from typing import List, Union, Literal, Optional, IO
from io import StringIO

from pyswip.prolog import Prolog


__all__ = "Matrix", "solve", "prolog_source"
__all__ = "Matrix", "prolog_source", "sample_puzzle", "solve"

_DIMENSION = 9
_SOURCE_PATH = "sudoku.pl"
Expand All @@ -38,6 +44,8 @@


class Matrix:
"""Represents a 9x9 Sudoku puzzle"""

def __init__(self, matrix: List[List[int]]) -> None:
if not matrix:
raise ValueError("matrix must be given")
Expand All @@ -49,7 +57,33 @@ def __init__(self, matrix: List[List[int]]) -> None:

@classmethod
def from_text(cls, text: str) -> "Matrix":
lines = text.strip().split("\n")
"""
Create a Matrix from the given string
The following are valid characters in the string:
* `.`: Blank column
* `1-9`: Numbers
The text must contain exactly 9 rows and 9 columns.
Each row ends with a newline character.
You can use blank lines and spaces/tabs between columns.
:param text: The text to use for creating the Matrix
>>> puzzle = Matrix.from_text('''
... . . 5 . 7 . 2 6 8
... . . 4 . . 2 . . .
... . . 1 . 9 . . . .
... . 8 . . . . 1 . .
... . 2 . 9 . . . 7 .
... . . 6 . . . . 3 .
... . . 2 . 4 . 7 . .
... . . . 5 . . 9 . .
... 9 5 7 . 3 . . . .
... ''')
"""
lines = [row for line in text.strip().split("\n") if (row := line.strip())]
dimension = len(lines)
rows = []
for i, line in enumerate(lines):
Expand Down Expand Up @@ -82,7 +116,25 @@ def __str__(self) -> str:
def __repr__(self) -> str:
return str(self.matrix)

def pretty_print(self, *, file=sys.stdout) -> None:
def pretty_print(self, *, file: Optional[IO] = None) -> None:
"""
Prints the matrix as a grid
:param file: The file to use for printing
>>> import sys
>>> puzzle = sample_puzzle()
>>> puzzle.pretty_print(file=sys.stdout)
. . 5 . 7 . 2 6 8
. . 4 . . 2 . . .
. . 1 . 9 . . . .
. 8 . . . . 1 . .
. 2 . 9 . . . 7 .
. . 6 . . . . 3 .
. . 2 . 4 . 7 . .
. . . 5 . . 9 . .
9 5 7 . 3 . . . .
"""
for row in self.matrix:
row = " ".join(str(x or ".") for x in row)
print(row, file=file)
Expand All @@ -92,12 +144,29 @@ def solve(matrix: Matrix) -> Union[Matrix, Literal[False]]:
"""
Solves the given Sudoku puzzle
Parameters:
matrix (Matrix): The matrix that contains the Sudoku puzzle
Returns:
Matrix: Solution matrix
False: If no solutions was found
:param matrix: The matrix that contains the Sudoku puzzle
>>> puzzle = sample_puzzle()
>>> print(puzzle)
. . 5 . 7 . 2 6 8
. . 4 . . 2 . . .
. . 1 . 9 . . . .
. 8 . . . . 1 . .
. 2 . 9 . . . 7 .
. . 6 . . . . 3 .
. . 2 . 4 . 7 . .
. . . 5 . . 9 . .
9 5 7 . 3 . . . .
>>> print(solve(puzzle))
3 9 5 4 7 1 2 6 8
8 7 4 6 5 2 3 9 1
2 6 1 3 9 8 5 4 7
5 8 9 7 6 3 1 2 4
1 2 3 9 8 4 6 7 5
7 4 6 2 1 5 8 3 9
6 1 2 8 4 9 7 5 3
4 3 8 5 2 7 9 1 6
9 5 7 1 3 6 4 8 2
"""
p = repr(matrix).replace("0", "_")
result = list(Prolog.query(f"L={p},sudoku(L)", maxresult=1))
Expand All @@ -110,15 +179,17 @@ def solve(matrix: Matrix) -> Union[Matrix, Literal[False]]:


def prolog_source() -> str:
"""Returns the Prolog source file that solves Sudoku puzzles"""
from pathlib import Path

path = Path(__file__).parent / _SOURCE_PATH
with open(path) as f:
return f.read()


def main():
puzzle = Matrix.from_text("""
def sample_puzzle() -> Matrix:
"""Returns the sample Sudoku puzzle"""
matrix = Matrix.from_text("""
. . 5 . 7 . 2 6 8
. . 4 . . 2 . . .
. . 1 . 9 . . . .
Expand All @@ -129,6 +200,11 @@ def main():
. . . 5 . . 9 . .
9 5 7 . 3 . . . .
""")
return matrix


def main():
puzzle = sample_puzzle()
print("\n-- PUZZLE --")
puzzle.pretty_print()
print("\n-- SOLUTION --")
Expand Down
Loading

0 comments on commit 1f06e6a

Please sign in to comment.