fix: add docs, tests; tweak some handler method signatures

This commit is contained in:
Lance Edgar 2025-01-12 01:10:52 -06:00
parent e4a4e85cf6
commit d11e186df9
16 changed files with 345 additions and 15 deletions

20
docs/Makefile Normal file
View file

@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

0
docs/_static/.keepme vendored Normal file
View file

View file

@ -0,0 +1,6 @@
``wutta_corepos.app``
=====================
.. automodule:: wutta_corepos.app
:members:

View file

@ -0,0 +1,6 @@
``wutta_corepos.conf``
======================
.. automodule:: wutta_corepos.conf
:members:

View file

@ -0,0 +1,6 @@
``wutta_corepos.handler``
=========================
.. automodule:: wutta_corepos.handler
:members:

View file

@ -0,0 +1,6 @@
``wutta_corepos``
=================
.. automodule:: wutta_corepos
:members:

38
docs/conf.py Normal file
View file

@ -0,0 +1,38 @@
# Configuration file for the Sphinx documentation builder.
#
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
from importlib.metadata import version as get_version
project = 'Wutta-COREPOS'
copyright = '2025, Lance Edgar'
author = 'Lance Edgar'
release = get_version('Wutta-COREPOS')
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.intersphinx',
'sphinx.ext.viewcode',
'sphinx.ext.todo',
]
templates_path = ['_templates']
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
intersphinx_mapping = {
'wuttjamaican': ('https://rattailproject.org/docs/wuttjamaican/', None),
}
# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
html_theme = 'furo'
html_static_path = ['_static']

28
docs/index.rst Normal file
View file

@ -0,0 +1,28 @@
Wutta-COREPOS
=============
This package adds basic integration with `CORE-POS`_, using
`pyCOREPOS`_.
Its main purpose is to setup DB connections for CORE Office.
.. _CORE-POS: https://www.core-pos.com/
.. _pyCOREPOS: https://pypi.org/project/pyCOREPOS/
.. toctree::
:maxdepth: 2
:caption: Documentation
narr/install
.. toctree::
:maxdepth: 1
:caption: API
api/wutta_corepos
api/wutta_corepos.app
api/wutta_corepos.conf
api/wutta_corepos.handler

35
docs/make.bat Normal file
View file

@ -0,0 +1,35 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=.
set BUILDDIR=_build
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.https://www.sphinx-doc.org/
exit /b 1
)
if "%1" == "" goto help
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
:end
popd

32
docs/narr/install.rst Normal file
View file

@ -0,0 +1,32 @@
Installation
============
This assumes you already have a :doc:`WuttJamaican app
<wuttjamaican:narr/install/index>` setup and working.
Install the Wutta-COREPOS package to your virtual environment:
.. code-block:: sh
pip install Wutta-COREPOS
Edit your :term:`config file` to add CORE-POS DB connection info, and
related settings. Note that so far, only CORE Office DB connections
are supported.
.. code-block:: ini
[corepos]
office.url = http://localhost/fannie/
[corepos.db.office_op]
default.url = mysql+mysqlconnector://localhost/core_op
[corepos.db.office_trans]
default.url = mysql+mysqlconnector://localhost/core_trans
[corepos.db.office_arch]
default.url = mysql+mysqlconnector://localhost/trans_archive
And that's it, the CORE-POS integration is configured.

View file

@ -36,6 +36,11 @@ class WuttaCoreposAppProvider(AppProvider):
""" """
def get_corepos_handler(self, **kwargs): def get_corepos_handler(self, **kwargs):
"""
Get the configured CORE-POS integration handler.
:rtype: :class:`~wutta_corepos.handler.CoreposHandler`
"""
if not hasattr(self, 'corepos_handler'): if not hasattr(self, 'corepos_handler'):
spec = self.config.get(f'{self.appname}.corepos_handler', spec = self.config.get(f'{self.appname}.corepos_handler',
default='wutta_corepos.handler:CoreposHandler') default='wutta_corepos.handler:CoreposHandler')

View file

@ -40,7 +40,7 @@ class WuttaCoreposConfigExtension(WuttaConfigExtension):
* ``office_trans`` (default name ``core_trans``) * ``office_trans`` (default name ``core_trans``)
* ``office_arch`` (default name ``trans_archive``) * ``office_arch`` (default name ``trans_archive``)
The config object will be given the following attributes: The :term:`config object` will be given the following attributes:
.. data:: core_office_op_engine .. data:: core_office_op_engine

View file

@ -38,6 +38,11 @@ class CoreposHandler(GenericHandler):
Returns the base URL for the CORE Office web app. Returns the base URL for the CORE Office web app.
Note that the return value is stripped of final slash. Note that the return value is stripped of final slash.
:param require: If true, an error is raised when URL cannot be
determined.
:returns: URL as string.
""" """
url = self.config.get('corepos.office.url', require=require) url = self.config.get('corepos.office.url', require=require)
if url: if url:
@ -45,40 +50,64 @@ class CoreposHandler(GenericHandler):
def get_office_department_url( def get_office_department_url(
self, self,
number, dept_id,
office_url=None, office_url=None,
require=False, require=False):
**kwargs):
""" """
Returns the CORE Office URL for a Department. Returns the CORE Office URL for a Department.
:param dept_id: Department ID for the URL.
:param office_url: Root URL from :meth:`get_office_url()`.
:param require: If true, an error is raised when URL cannot be
determined.
:returns: URL as string.
""" """
if not office_url: if not office_url:
office_url = self.get_office_url(require=require) office_url = self.get_office_url(require=require)
if office_url: if office_url:
return f'{office_url}/item/departments/DepartmentEditor.php?did={number}' return f'{office_url}/item/departments/DepartmentEditor.php?did={dept_id}'
def get_office_likecode_url( def get_office_likecode_url(
self, self,
id, likecode_id,
office_url=None, office_url=None,
require=False, require=False):
**kwargs):
""" """
Returns the CORE Office URL for a Like Code. Returns the CORE Office URL for a Like Code.
:param likecode_id: Like Code ID for the URL.
:param office_url: Root URL from :meth:`get_office_url()`.
:param require: If true, an error is raised when URL cannot be
determined.
:returns: URL as string.
""" """
if not office_url: if not office_url:
office_url = self.get_office_url(require=require) office_url = self.get_office_url(require=require)
if office_url: if office_url:
return f'{office_url}/item/likecodes/LikeCodeEditor.php?start={id}' return f'{office_url}/item/likecodes/LikeCodeEditor.php?start={likecode_id}'
def get_office_product_url( def get_office_product_url(
self, self,
upc, upc,
office_url=None, office_url=None,
require=False, require=False):
**kwargs):
""" """
Returns the CORE Office URL for a Product. Returns the CORE Office URL for a Product.
:param upc: UPC for the URL.
:param office_url: Root URL from :meth:`get_office_url()`.
:param require: If true, an error is raised when URL cannot be
determined.
:returns: URL as string.
""" """
if not office_url: if not office_url:
office_url = self.get_office_url(require=require) office_url = self.get_office_url(require=require)
@ -87,14 +116,22 @@ class CoreposHandler(GenericHandler):
def get_office_vendor_url( def get_office_vendor_url(
self, self,
id, vend_id,
office_url=None, office_url=None,
require=False, require=False):
**kwargs):
""" """
Returns the CORE Office URL for a Vendor. Returns the CORE Office URL for a Vendor.
:param vend_id: Vendor ID for the URL.
:param office_url: Root URL from :meth:`get_office_url()`.
:param require: If true, an error is raised when URL cannot be
determined.
:returns: URL as string.
""" """
if not office_url: if not office_url:
office_url = self.get_office_url(require=require) office_url = self.get_office_url(require=require)
if office_url: if office_url:
return f'{office_url}/item/vendors/VendorIndexPage.php?vid={id}' return f'{office_url}/item/vendors/VendorIndexPage.php?vid={vend_id}'

16
tests/test_app.py Normal file
View file

@ -0,0 +1,16 @@
# -*- coding: utf-8; -*-
from wuttjamaican.testing import ConfigTestCase
from wutta_corepos import app as mod
from wutta_corepos.handler import CoreposHandler
class TestWuttaCoreposAppProvider(ConfigTestCase):
def make_provider(self):
return mod.WuttaCoreposAppProvider(self.config)
def test_get_report_handler(self):
handler = self.app.get_corepos_handler()
self.assertIsInstance(handler, CoreposHandler)

29
tests/test_conf.py Normal file
View file

@ -0,0 +1,29 @@
# -*- coding: utf-8; -*-
from unittest import TestCase
from wuttjamaican.conf import WuttaConfig
from wutta_corepos import conf as mod
class TestWuttaCoreposConfigExtension(TestCase):
def test_configure(self):
config = WuttaConfig()
# no engines by default
self.assertFalse(hasattr(config, 'core_office_op_engine'))
self.assertFalse(hasattr(config, 'core_office_trans_engine'))
self.assertFalse(hasattr(config, 'core_office_arch_engine'))
ext = mod.WuttaCoreposConfigExtension()
ext.configure(config)
self.assertIsNone(config.core_office_op_engine)
self.assertIsNone(config.core_office_trans_engine)
self.assertIsNone(config.core_office_arch_engine)
# but config can change that
config.setdefault('corepos.db.office_op.default.url', 'sqlite://')
ext.configure(config)
self.assertIsNotNone(config.core_office_op_engine)
self.assertEqual(str(config.core_office_op_engine.url), 'sqlite://')

66
tests/test_handler.py Normal file
View file

@ -0,0 +1,66 @@
# -*- coding: utf-8; -*-
from wuttjamaican.testing import ConfigTestCase
from wuttjamaican.exc import ConfigurationError
from wutta_corepos import handler as mod
class TestCoreposHandler(ConfigTestCase):
def make_handler(self):
return mod.CoreposHandler(self.config)
def test_get_office_url(self):
handler = self.make_handler()
# null by default
self.assertIsNone(handler.get_office_url())
# error if required
self.assertRaises(ConfigurationError, handler.get_office_url, require=True)
# config can specify (traliing slash is stripped)
self.config.setdefault('corepos.office.url', 'http://localhost/fannie/')
self.assertEqual(handler.get_office_url(), 'http://localhost/fannie')
self.assertEqual(handler.get_office_url(require=True), 'http://localhost/fannie')
def test_get_office_department_url(self):
handler = self.make_handler()
# null
self.assertIsNone(handler.get_office_department_url(7))
# typical
self.config.setdefault('corepos.office.url', 'http://localhost/fannie/')
self.assertEqual(handler.get_office_department_url(7), 'http://localhost/fannie/item/departments/DepartmentEditor.php?did=7')
def test_get_office_likecode_url(self):
handler = self.make_handler()
# null
self.assertIsNone(handler.get_office_likecode_url(7))
# typical
self.config.setdefault('corepos.office.url', 'http://localhost/fannie/')
self.assertEqual(handler.get_office_likecode_url(7), 'http://localhost/fannie/item/likecodes/LikeCodeEditor.php?start=7')
def test_get_office_product_url(self):
handler = self.make_handler()
# null
self.assertIsNone(handler.get_office_product_url('07430500132'))
# typical
self.config.setdefault('corepos.office.url', 'http://localhost/fannie/')
self.assertEqual(handler.get_office_product_url('07430500132'), 'http://localhost/fannie/item/ItemEditorPage.php?searchupc=07430500132')
def test_get_office_vendor_url(self):
handler = self.make_handler()
# null
self.assertIsNone(handler.get_office_vendor_url(7))
# typical
self.config.setdefault('corepos.office.url', 'http://localhost/fannie/')
self.assertEqual(handler.get_office_vendor_url(7), 'http://localhost/fannie/item/vendors/VendorIndexPage.php?vid=7')