diff --git a/.gitignore b/.gitignore
index 7893476..5d6335c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1 @@
-*~
-*.pyc
-dist/
tailbone_woocommerce.egg-info/
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fa1effb..220b0d8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,12 +5,6 @@ All notable changes to tailbone-woocommerce will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
-## v0.2.0 (2024-06-11)
-
-### Feat
-
-- switch from setup.cfg to pyproject.toml + hatchling
-
## [0.1.0] - 2021-01-21
### Changed
- Initial release.
diff --git a/README.md b/README.md
deleted file mode 100644
index 873af83..0000000
--- a/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-
-# tailbone-woocommerce
-
-Rattail is a retail software framework, released under the GNU General
-Public License.
-
-This package contains software interfaces for the
-[WooCommerce](https://woocommerce.com/) system.
-
-Please see the [Rattail Project](https://rattailproject.org/) for more
-information.
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..d768e06
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,14 @@
+
+tailbone-woocommerce
+====================
+
+Rattail is a retail software framework, released under the GNU General Public
+License.
+
+This package contains software interfaces for the `WooCommerce`_ system.
+
+.. _WooCommerce: https://woocommerce.com/
+
+Please see the `Rattail Project`_ for more information.
+
+.. _`Rattail Project`: https://rattailproject.org/
diff --git a/pyproject.toml b/pyproject.toml
deleted file mode 100644
index 100dd71..0000000
--- a/pyproject.toml
+++ /dev/null
@@ -1,42 +0,0 @@
-
-[build-system]
-requires = ["hatchling"]
-build-backend = "hatchling.build"
-
-
-[project]
-name = "tailbone-woocommerce"
-version = "0.2.0"
-description = "Tailbone integration for WooCommerce"
-readme = "README.md"
-authors = [{name = "Lance Edgar", email = "lance@edbob.org"}]
-license = {text = "GNU GPL v3+"}
-classifiers = [
- "Development Status :: 4 - Beta",
- "Environment :: Web Environment",
- "Intended Audience :: Developers",
- "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
- "Natural Language :: English",
- "Operating System :: OS Independent",
- "Programming Language :: Python",
- "Programming Language :: Python :: 3",
- "Topic :: Office/Business",
- "Topic :: Software Development :: Libraries :: Python Modules",
-]
-dependencies = [
- "rattail",
- "rattail-woocommerce",
- "Tailbone",
-]
-
-
-[project.urls]
-Homepage = "https://rattailproject.org"
-Repository = "https://kallithea.rattailproject.org/rattail-project/tailbone-woocommerce"
-Changelog = "https://kallithea.rattailproject.org/rattail-project/tailbone-woocommerce/files/master/CHANGELOG.md"
-
-
-[tool.commitizen]
-version_provider = "pep621"
-tag_format = "v$version"
-update_changelog_on_bump = true
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..ffea671
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,95 @@
+# -*- coding: utf-8; -*-
+################################################################################
+#
+# Rattail -- Retail Software Framework
+# Copyright © 2010-2021 Lance Edgar
+#
+# This file is part of Rattail.
+#
+# Rattail is free software: you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# Rattail. If not, see .
+#
+################################################################################
+
+import os
+from setuptools import setup, find_packages
+
+
+here = os.path.abspath(os.path.dirname(__file__))
+exec(open(os.path.join(here, 'tailbone_woocommerce', '_version.py')).read())
+README = open(os.path.join(here, 'README.rst')).read()
+
+
+requires = [
+ #
+ # Version numbers within comments below have specific meanings.
+ # Basically the 'low' value is a "soft low," and 'high' a "soft high."
+ # In other words:
+ #
+ # If either a 'low' or 'high' value exists, the primary point to be
+ # made about the value is that it represents the most current (stable)
+ # version available for the package (assuming typical public access
+ # methods) whenever this project was started and/or documented.
+ # Therefore:
+ #
+ # If a 'low' version is present, you should know that attempts to use
+ # versions of the package significantly older than the 'low' version
+ # may not yield happy results. (A "hard" high limit may or may not be
+ # indicated by a true version requirement.)
+ #
+ # Similarly, if a 'high' version is present, and especially if this
+ # project has laid dormant for a while, you may need to refactor a bit
+ # when attempting to support a more recent version of the package. (A
+ # "hard" low limit should be indicated by a true version requirement
+ # when a 'high' version is present.)
+ #
+ # In any case, developers and other users are encouraged to play
+ # outside the lines with regard to these soft limits. If bugs are
+ # encountered then they should be filed as such.
+ #
+ # package # low high
+
+ 'rattail', # 0.9.138
+ 'rattail-woocommerce', # 0.1.0
+ 'Tailbone', # 0.8.103
+]
+
+
+setup(
+ name = "tailbone-woocommerce",
+ version = __version__,
+ author = "Lance Edgar",
+ author_email = "lance@edbob.org",
+ url = "https://rattailproject.org/",
+ license = "GNU GPL v3",
+ description = "Tailbone integration for WooCommerce",
+ long_description = README,
+
+ classifiers = [
+ 'Development Status :: 4 - Beta',
+ 'Environment :: Web Environment',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)',
+ 'Natural Language :: English',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python',
+ 'Programming Language :: Python :: 3',
+ 'Topic :: Office/Business',
+ 'Topic :: Software Development :: Libraries :: Python Modules',
+ ],
+
+ install_requires = requires,
+ packages = find_packages(),
+ include_package_data = True,
+ zip_safe = False,
+)
diff --git a/tailbone_woocommerce/_version.py b/tailbone_woocommerce/_version.py
index 5c5048a..e41b669 100644
--- a/tailbone_woocommerce/_version.py
+++ b/tailbone_woocommerce/_version.py
@@ -1,6 +1,3 @@
# -*- coding: utf-8; -*-
-from importlib.metadata import version
-
-
-__version__ = version('tailbone-woocommerce')
+__version__ = '0.1.0'
diff --git a/tailbone_woocommerce/templates/products/view.mako b/tailbone_woocommerce/templates/products/view.mako
new file mode 100644
index 0000000..29c92d4
--- /dev/null
+++ b/tailbone_woocommerce/templates/products/view.mako
@@ -0,0 +1,52 @@
+## -*- coding: utf-8; -*-
+<%inherit file="tailbone:templates/products/view.mako" />
+
+<%def name="object_helpers()">
+ ${parent.object_helpers()}
+ ${self.render_xref_helper()}
+%def>
+
+<%def name="render_xref_store_button()">
+
+ View in WooCommerce Store
+
+%def>
+
+<%def name="render_xref_admin_button()">
+
+ View in WooCommerce Admin
+
+%def>
+
+<%def name="render_xref_helper()">
+
+
Cross-Reference
+
+ ${self.render_xref_store_button()}
+ ${self.render_xref_admin_button()}
+
+
+%def>
+
+<%def name="extra_main_fields(form)">
+ ${parent.extra_main_fields(form)}
+ ${self.extra_main_fields_woocommerce(form)}
+%def>
+
+<%def name="extra_main_fields_woocommerce(form)">
+ ${form.render_field_readonly('woocommerce_id')}
+%def>
+
+${parent.body()}
diff --git a/tailbone_woocommerce/views/__init__.py b/tailbone_woocommerce/views/__init__.py
index 6be242f..e69de29 100644
--- a/tailbone_woocommerce/views/__init__.py
+++ b/tailbone_woocommerce/views/__init__.py
@@ -1,29 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# Rattail -- Retail Software Framework
-# Copyright © 2010-2022 Lance Edgar
-#
-# This file is part of Rattail.
-#
-# Rattail is free software: you can redistribute it and/or modify it under the
-# terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# Rattail. If not, see .
-#
-################################################################################
-"""
-Views w/ WooCommerce integration
-"""
-
-
-def includeme(config):
- config.include('tailbone_woocommerce.views.products')
diff --git a/tailbone_woocommerce/views/products.py b/tailbone_woocommerce/views/products.py
index f38525e..545d22f 100644
--- a/tailbone_woocommerce/views/products.py
+++ b/tailbone_woocommerce/views/products.py
@@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
-# Copyright © 2010-2022 Lance Edgar
+# Copyright © 2010-2021 Lance Edgar
#
# This file is part of Rattail.
#
@@ -28,68 +28,72 @@ from sqlalchemy import orm
from rattail_woocommerce.config import woocommerce_admin_product_url
-from webhelpers2.html import tags
-
-from tailbone.views import ViewSupplement
+from tailbone.views import products as base
-class ProductViewSupplement(ViewSupplement):
+class ProductView(base.ProductsView):
"""
- Product view supplement for WooCommerce integration
+ Master view for the Product class.
"""
- route_prefix = 'products'
-
labels = {
'woocommerce_id': "WooCommerce ID",
}
- def get_grid_query(self, query):
+ @property
+ def form_fields(self):
+ fields = super(ProductView, self).form_fields
+ return self.woocommerce_add_form_fields(fields)
+
+ def woocommerce_add_form_fields(self, fields):
+ fields.extend([
+ 'woocommerce_id',
+ ])
+ return fields
+
+ def query(self, session):
+ query = super(ProductView, self).query(session)
+ return self.woocommerce_modify_query(query)
+
+ def woocommerce_modify_query(self, query):
model = self.model
return query.outerjoin(model.WooProductExtension)
def configure_grid(self, g):
+ super(ProductView, self).configure_grid(g)
+ self.woocommerce_configure_grid(g)
+
+ def woocommerce_configure_grid(self, g):
model = self.model
g.set_filter('woocommerce_id', model.WooProductExtension.woocommerce_id)
def configure_form(self, f):
- if not self.master.creating:
- f.append('woocommerce_id')
+ super(ProductView, self).configure_form(f)
+ self.woocommerce_configure_form(f)
+
+ def woocommerce_configure_form(self, f):
+ f.set_required('woocommerce_id', False)
+ if self.creating:
+ f.remove('woocommerce_id')
def get_version_child_classes(self):
+ classes = super(ProductView, self).get_version_child_classes()
+ return self.woocommerce_add_version_classes(classes)
+
+ def woocommerce_add_version_classes(self, classes):
model = self.model
- return [model.WooProductExtension]
+ classes.extend([
+ model.WooProductExtension,
+ ])
+ return classes
- def get_panel_fields_main(self, product):
- return ['woocommerce_id']
-
- def get_xref_buttons(self, product):
- buttons = []
-
- woo_cached = self.get_woo_cached_product(product)
- if woo_cached:
- buttons.append({'url': woo_cached.permalink,
- 'text': "View in WooCommerce Store"})
-
- woo_id = woo_cached.id if woo_cached else product.woocommerce_id
- if woo_id:
- url = woocommerce_admin_product_url(self.rattail_config, woo_id)
- if url:
- buttons.append({'url': url,
- 'text': "View in WooCommerce Admin"})
-
- return buttons
-
- def get_xref_links(self, product):
- if product.woocommerce_cache_product:
- url = self.request.route_url('woocommerce.products.view',
- uuid=product.woocommerce_cache_product.uuid)
- return [tags.link_to("View WooCommerce Product", url)]
+ def template_kwargs_view(self, **kwargs):
+ kwargs = super(ProductView, self).template_kwargs_view(**kwargs)
+ return self.woocommerce_template_kwargs_view(**kwargs)
def get_woo_cached_product(self, product):
"""
Tries to identify the WooCacheProduct for the given Rattail Product.
"""
- model = self.model
woo_cached = None
if product.woocommerce_cache_product:
@@ -98,6 +102,7 @@ class ProductViewSupplement(ViewSupplement):
elif product.item_id:
# try to find matching woo product, even though not linked
+ model = self.rattail_config.get_model()
try:
woo_cached = self.Session.query(model.WooCacheProduct)\
.filter(model.WooCacheProduct.sku == product.item_id)\
@@ -107,6 +112,45 @@ class ProductViewSupplement(ViewSupplement):
return woo_cached
+ def woocommerce_template_kwargs_view(self, **kwargs):
+ product = kwargs['instance']
+ woo_cached = self.get_woo_cached_product(product)
+
+ # WooCommerce Store URL
+ store_url = why_not = None
+ if woo_cached:
+ store_url = woo_cached.permalink
+ else:
+ why_not = "WooCommerce cache product not found"
+ kwargs['woocommerce_store_url'] = store_url
+ kwargs['woocommerce_store_why_no_url'] = why_not
+
+ # WooCommerce Admin URL
+ admin_url = why_not = None
+ woo_id = woo_cached.id if woo_cached else product.woocommerce_id
+ if woo_id:
+ admin_url = woocommerce_admin_product_url(self.rattail_config,
+ woo_id)
+ if not admin_url:
+ why_not = "WooCommerce Admin URL is not configured"
+ else:
+ why_not = "Product is not known to exist in WooCommerce"
+ kwargs['woocommerce_admin_url'] = admin_url
+ kwargs['woocommerce_admin_why_no_url'] = why_not
+
+ return kwargs
+
def includeme(config):
- ProductViewSupplement.defaults(config)
+
+ # TODO: getting pretty tired of copy/pasting this extra config...
+ config.add_route('products.autocomplete', '/products/autocomplete')
+ config.add_view(base.ProductsAutocomplete, route_name='products.autocomplete',
+ renderer='json', permission='products.list')
+
+ # TODO: getting pretty tired of copy/pasting this extra config...
+ config.add_route('products.print_labels', '/products/labels')
+ config.add_view(base.print_labels, route_name='products.print_labels',
+ renderer='json', permission='products.print_labels')
+
+ ProductView.defaults(config)
diff --git a/tasks.py b/tasks.py
index a376936..469b737 100644
--- a/tasks.py
+++ b/tasks.py
@@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
-# Copyright © 2010-2024 Lance Edgar
+# Copyright © 2010-2021 Lance Edgar
#
# This file is part of Rattail.
#
@@ -30,14 +30,15 @@ import shutil
from invoke import task
+here = os.path.abspath(os.path.dirname(__file__))
+exec(open(os.path.join(here, 'tailbone_woocommerce', '_version.py')).read())
+
+
@task
-def release(c):
+def release(ctx):
"""
Release a new version of 'tailbone-woocommerce'.
"""
- if os.path.exists('dist'):
- shutil.rmtree('dist')
- if os.path.exists('tailbone_woocommerce.egg-info'):
- shutil.rmtree('tailbone_woocommerce.egg-info')
- c.run('python -m build --sdist')
- c.run('twine upload dist/*')
+ shutil.rmtree('tailbone_woocommerce.egg-info')
+ ctx.run('python setup.py sdist --formats=gztar')
+ ctx.run('twine upload dist/tailbone-woocommerce-{}.tar.gz'.format(__version__))