Skip to content

Commit

Permalink
Added documentation and types for prolog and examples packages
Browse files Browse the repository at this point in the history
  • Loading branch information
yuce committed Oct 20, 2024
1 parent 2403dca commit 3018e0e
Show file tree
Hide file tree
Showing 14 changed files with 347 additions and 75 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: 91 additions & 13 deletions src/pyswip/examples/sudoku.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,22 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

"""
Sudoku example
You can run this module using::
$ python3 -m pyswip.examples.sudoku
"""

import sys
from typing import List, Union, Literal
from optparse import Option
from typing import List, Union, Literal, TextIO, 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 +46,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 +59,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 = [l for line in text.strip().split("\n") if (l := line.strip())]
dimension = len(lines)
rows = []
for i, line in enumerate(lines):
Expand Down Expand Up @@ -82,7 +118,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 +146,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 +181,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 +202,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 3018e0e

Please sign in to comment.