Compare commits

...

18 commits

Author SHA1 Message Date
Lance Edgar 06394dc3e3 docs: update project links, kallithea -> forgejo 2024-09-14 10:47:30 -05:00
Lance Edgar 70b103ebd8 docs: use markdown for readme file 2024-09-13 18:21:24 -05:00
Lance Edgar b96c828fa3 fix: avoid deprecated base class for config extension 2024-08-16 13:34:48 -05:00
Lance Edgar 1fb3ee10d0 fix: update config for custom emails
per upstream changes
2024-07-09 10:16:31 -05:00
Lance Edgar 95f8ae318a fix: refactor custom menu builder, to inherit some menus
also rename config extension, per conventions
2024-07-01 13:25:31 -05:00
Lance Edgar f0dc65ee08 bump: version 0.3.0 → 0.3.1 2024-07-01 11:46:10 -05:00
Lance Edgar ab12cba1d5 fix: remove legacy command definitions 2024-07-01 11:45:41 -05:00
Lance Edgar 1c14ad72cd bump: version 0.2.0 → 0.3.0 2024-07-01 11:22:57 -05:00
Lance Edgar 4c9c321608 feat: migrate all commands to use typer framework 2024-07-01 11:21:53 -05:00
Lance Edgar 4588fb8179 use furo docs theme instead of alabaster 2024-07-01 11:09:44 -05:00
Lance Edgar 43a6c56844 bump: version 0.1.0 → 0.2.0 2024-07-01 11:03:21 -05:00
Lance Edgar 3af49e2e62 feat: switch from setup.cfg to pyproject.toml + hatchling 2024-07-01 11:03:11 -05:00
Lance Edgar 95e89a6081 Start docs for customizing the app
(not much here yet, but will grow over time...)
2019-08-20 12:24:16 -05:00
Lance Edgar 088fd4a6a5 Remove unwanted web template overrides
those are no longer needed these days
2019-08-17 19:03:21 -05:00
Lance Edgar 2adb18534c Add docs for running web app 2019-08-17 18:54:04 -05:00
Lance Edgar 1660774ad2 Add docs for establishing main app DB 2019-08-17 03:52:38 -05:00
Lance Edgar 6285ba3cc8 Add docs for building a version release for project 2019-08-17 02:41:26 -05:00
Lance Edgar 5fb47aa4c0 Add tasks file, w/ "release" task
now version 0.1.0 lives on PyPI
2019-08-17 01:27:45 -05:00
24 changed files with 612 additions and 286 deletions

3
.gitignore vendored
View file

@ -1,3 +1,6 @@
*~
*.pyc
dist/
rattail_tutorial.egg-info/
docs/_build/
.tox/

View file

@ -5,6 +5,24 @@ All notable changes to rattail-tutorial will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project (probably doesn't) adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## v0.3.1 (2024-07-01)
### Fix
- remove legacy command definitions
## v0.3.0 (2024-07-01)
### Feat
- migrate all commands to use `typer` framework
## v0.2.0 (2024-07-01)
### Feat
- switch from setup.cfg to pyproject.toml + hatchling
## [0.1.0] - 2019-08-15
### Changed
- Initial version, with very basic (mostly generated) app.

View file

@ -1,13 +1,9 @@
.. -*- mode: rst -*-
rattail-tutorial
================
# rattail-tutorial
This project is intended for use as a "tutorial" for Rattail app development.
It contains documentation for the tutorial itself, but also contains
code for the tutorial app, which users may run locally for testing.
See the `Rattail website`_ for more info.
.. _`Rattail website`: https://rattailproject.org/
See the [Rattail website](https://rattailproject.org/) for more info.

3
Vagrantfile vendored
View file

@ -5,4 +5,7 @@ Vagrant.configure("2") do |config|
# target machine runs Debian 10 "buster"
config.vm.box = "debian/buster64"
# rattail-tutorial web app
config.vm.network "forwarded_port", guest: 9080, host: 9080
end

View file

@ -17,12 +17,14 @@
# -- Project information -----------------------------------------------------
from importlib.metadata import version as get_version
project = 'rattail-tutorial'
copyright = '2019, Lance Edgar'
copyright = '2019-2024, Lance Edgar'
author = 'Lance Edgar'
# The full version, including alpha/beta/rc tags
release = '0.1'
release = get_version('rattail-tutorial')
# -- General configuration ---------------------------------------------------
@ -51,7 +53,7 @@ todo_include_todos = True
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'alabaster'
html_theme = 'furo'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,

View file

@ -125,7 +125,7 @@ rattail-tutorial app instead, you should do this::
mkdir -p ~/src
cd ~/src
git clone https://rattailproject.org/git/rattail-tutorial.git
git clone https://forgejo.wuttaproject.org/rattail/rattail-tutorial.git
pip install -e rattail-tutorial
Creating the Project

View file

@ -0,0 +1,89 @@
Hide / Disable Unwanted Web Views
=================================
The first thing we'll want to do is take stock of the views currently exposed
by the web app, and either hide or outright "remove" any we don't want (yet).
There are sort of 3 different aspects to whether or not a particular web view
is "available" for a given user:
* is the view even defined?
* does user have permission to access the view?
* is there a menu (or other) link to the view?
Removing a (Master) View
------------------------
There are a few "core" web views which will "always" be defined, but the vast
majority are really optional. The so-called "master" web views, each of which
basically corresponds to a particular table in the DB, are (almost?) entirely
optional. For instance if your organization needs to track customers but not
products, within your Poser app, then you might go so far as to "remove" the
product views from your app.
If you do this, then e.g. navigating to http://localhost:9080/products/ (or
whatever your URL is) would result in a 404 not found error regardless of user
permissions, i.e. even if you "become root". However by default (using code
generated via scaffold) the product views *are* enabled, so this URL *would*
work.
Whether or not a given view(s) is "defined" will depend on whether or not the
module containing this view(s) has been "included" by the Pyramid (web app)
Configurator object. In other words we're leveraging this "include" concept
from `Pyramid`_ in order to control which views are brought into the running
app.
.. _Pyramid: https://trypyramid.com/
In practice what that means is usually just that you must curate the list of
views which are included, within your own project. This config thing works
recursively, but we try to keep the primary list within a conventional place.
In our (tutorial's) case this file is at
``~/src/rattail-tutorial/rattail_tutorial/web/views/__init__.py`` and by
default (freshly generated via scaffold) it looks something like this::
def includeme(config):
# core views
config.include('rattail_tutorial.web.views.common')
config.include('tailbone.views.auth')
config.include('tailbone.views.tables')
config.include('tailbone.views.upgrades')
config.include('tailbone.views.progress')
# main table views
config.include('tailbone.views.brands')
config.include('tailbone.views.customers')
config.include('tailbone.views.customergroups')
config.include('tailbone.views.datasync')
config.include('tailbone.views.departments')
config.include('tailbone.views.email')
config.include('tailbone.views.employees')
config.include('tailbone.views.messages')
config.include('tailbone.views.people')
config.include('tailbone.views.products')
config.include('tailbone.views.reportcodes')
config.include('tailbone.views.roles')
config.include('tailbone.views.settings')
config.include('tailbone.views.shifts')
config.include('tailbone.views.stores')
config.include('tailbone.views.subdepartments')
config.include('tailbone.views.users')
config.include('tailbone.views.vendors')
# batch views
config.include('tailbone.views.handheld')
config.include('tailbone.views.inventory')
In our case the only thing we'll remove for now is the "shifts" entry, i.e. we
wish to remove the line that says::
config.include('tailbone.views.shifts')
That's because these views have to do with staff scheduling and time clock
stuff, which (at least for now) we won't concern ourselves with.
Note that the underlying *tables* which might contain such data, are left in
place within our database. We're just declaring that we do not need our web
app to support master views for interacting with those tables.

22
docs/customize/index.rst Normal file
View file

@ -0,0 +1,22 @@
Customizing the App!
====================
Now that you've made it through the "setup" gauntlet, it's finally time for
some fun stuff.
As we're building this tutorial, at this point our project is *basically* the
same as any other "Poser" project, as generated via scaffold. But as we keep
going, our project will become more and more customized for the purposes of the
tutorial.
So if you have just created a new project, some of this might make more sense
to you, vs. if you're running the rattail-tutorial project itself, many things
described in this section will have already been done (and then some) to the
code base, so you should keep that in mind when reading.
.. toctree::
:maxdepth: 2
disable-web-view

View file

@ -55,6 +55,10 @@ Table of Contents
create-project
start-docs
configure
pkg-release
make-db
run-webapp
customize/index
Indices and tables

87
docs/make-db.rst Normal file
View file

@ -0,0 +1,87 @@
.. highlight:: sh
Establish Main App Database
===========================
Now that you have a hang of how to use the Rattail-style command line
(somewhat), let's move on to the database.
The main reason to wait until now to add a DB to the mix, was simply to show
that the "core" of Rattail does not need a DB. However in practice there *are*
definitely some commands which Rattail comes with out of the box, and which
also would require one or even multiple databases to be present.
Create User for PostgreSQL
--------------------------
Before we make our database, let's first establish a user account within
Postgres, which we will designate as the "owner" of our database(s).
It is convention within Rattail, to create a PG user named "rattail" for this
purpose. You are free to use another name if you prefer::
sudo -u postgres createuser --no-createdb --no-createrole --no-superuser rattail
You also should declare a password for the user::
sudo -u postgres psql -c "alter user rattail password 'newpassword'"
Create Database
---------------
Now that we know who to use as the "owner" we will create a new Postgres
database::
sudo -u postgres createdb --owner rattail rattut
Of course we named our database "rattut" here only because we're assuming this
tutorial project is the app, but your name may be different.
At this point you should update your ``app/rattail.conf`` file to reflect your
chosen database name and user credentials:
.. code-block:: ini
[rattail.db]
default.url = postgresql://rattail:newpassword@localhost/rattut
Install DB Schema
-----------------
So you have a DB but its empty; you can confirm that with::
sudo -u postgres psql -c '\d' rattut
But we'll fix that now. Schema is managed entirely via Alembic "version"
scripts, so to install the schema we merely run all the scripts::
cdvirtualenv
bin/alembic -c app/rattail.conf upgrade heads
(Note that you must use ``rattail.conf`` for that; ``quiet.conf`` won't work.)
If you check the DB again you should see a good amount of tables.
.. _make-user:
Create Admin User in DB
-----------------------
We include this here not so much because you *need* an admin user in your DB at
this point (although you will for the web app), but rather just to confirm that
everything is setup correctly thus far.
You currently should have no users in your DB::
sudo -u postgres psql -c 'select * from "user"' rattut
Okay then let's make an admin user for you::
bin/rattail -c app/quiet.conf make-user --admin myusername
Now if you query the ``user`` table again you should see your new account.

118
docs/pkg-release.rst Normal file
View file

@ -0,0 +1,118 @@
.. highlight:: sh
Build a Release for the Project
===============================
Even though our app does very little at this stage, we wish to go ahead and
"release" our first version for it.
.. note::
Whether or not you actually need to build releases for your project, may
depend on your use case. For instance if you have reason to run the app(s)
directly from source (i.e. git HEAD) then you may have no use for a built
package.
Project Versioning
------------------
The project's current version "number" is kept in only one place really, in our
case ``~/src/rattail-tutorial/rattail_tutorial/_version.py``. Other files are
configured to read the current project version from there.
The initial version for a new project will generally be '0.1.0' and it's
assumed that subsequent versions will be '0.1.1' then '0.1.2' etc. until you've
decided that it's time to do a '0.2.0' release, and the cycle begins again.
You can be as aggressive or conservative as you like when it comes to
incrementing the more "major" parts of the version number, e.g. you can
increment conservatively to where you've just released say, '0.1.427' before you
finally go to '0.2.0'. The only real "requirement" (assumption) here is that
you will build a new version release *every time* you update the production
environment(s). Sometimes that may mean multiple releases in a given day,
e.g. if the first one ships with a bug and you have to push a release to fix.
Install Invoke
--------------
While you can most certainly go about the build/release task in various ways,
the convention within Rattail-land is to use `Invoke`_.
.. _Invoke: https://www.pyinvoke.org/
So next we'll install that to your virtualenv::
pip install invoke
You may also want to declare this within your project's dependencies (in
``setup.py``), but that's up to you.
Create Tasks File
-----------------
The ``invoke`` command will invoke tasks which we have defined in a tasks file.
(Duh!)
We will now create a file at ``~/src/rattail-tutorial/tasks.py`` and in it
place some minimal contents:
.. code-block:: python3
# -*- coding: utf-8; -*-
"""
Tasks for 'rattail-tutorial' project
"""
from invoke import task
# this is needed to read current `__version__` value
#import os
#here = os.path.abspath(os.path.dirname(__file__))
#exec(open(os.path.join(here, 'rattail_tutorial', '_version.py')).read())
@task
def release(c):
"""
Release a new version of `rattail-tutorial`.
"""
# clear out previous package info
c.run('rm -rf rattail_tutorial.egg-info')
# build fresh package!
c.run('python setup.py sdist --formats=gztar')
# enable this if you intend to publish package to PyPI
#c.run('twine upload dist/rattail-tutorial-{}.tar.gz'.format(__version__))
If you're creating your own project then you can use the above as a starting
point for your own file. Instead of using ``twine`` to upload the package to
`PyPI`_, you may need to push to some private package repository which you
control.
.. _PyPI: https://pypi.org/
Run Release Task
----------------
As you can see above, ``release`` is the one and only task we have defined so
far. In most cases that will be the only task you ever define for the project,
but YMMV.
At any rate it's all we need for now, so let's run it::
cd ~/src/rattail-tutorial
invoke release
If you're feeling lazy you can even shorten that second one to::
inv release
This will build a new "release" which may then be found within e.g. the
``~/src/rattail-tutorial/dist/`` folder. Depending on the specifics of your
tasks file, this release may also be uploaded to some (public or private)
package index.

77
docs/run-webapp.rst Normal file
View file

@ -0,0 +1,77 @@
.. highlight:: sh
Run the Web App
===============
At this point we assume you already have a project installed to your
virtualenv, and have done basic configuration as well as established your app
database.
Make/Edit Config
----------------
If you've been following along with this tutorial you may have already done
this step, but in any case we'll revisit now.
If you do *not* yet have a file at e.g. ``/srv/envs/rattut/app/web.conf`` then
you should now run::
cdvirtualenv app
rattail make-config -T web
Then you must edit the generated file, looking for TODO notes and such, and
generally tweaking things to your liking.
Start the Web App
-----------------
The web app is effectively a daemon, in that it's meant to be a long-running
process which continues to listen for and respond to incoming requests.
In production, this may be wired up in various ways, but for now we're only
concerned with development, where we'll be starting the web app "server" from
command line::
cdvirtualenv
bin/pserve --reload file+ini:app/web.conf
Note that this command will "block" - meaning control will not immediately fall
back to your shell prompt. You may use Ctrl+C whenever you like, to kill the
web app.
Browse the Web App
------------------
This will only work when the above ``pserve`` command is running, but assuming
it is currently, you can access the web app at http://localhost:9080/
Note that the default ``web.conf`` specifies 9080 as the port on which the web
app will listen. You can modify this as needed, but if you do, and are also
using Vagrant, you may also need to modify your ``Vagrantfile`` (and do a
``vagrant reload``).
Login to Web App
----------------
If you've been following along with the tutorial then you probably have already
created an admin account for yourself. But in case you haven't, please see
:ref:`make-user`.
Once that's set then you should be able to login to the web app with those same
credentials.
The very first thing you see is likely "not much" - most of the menu will be
hidden to you, since by default you do not have sufficient permissions to
access the features they represent.
However you are an "admin" user - which really just means your user account
belongs to the special "Administrators" role. This role is special in that
anyone who belongs to it, is given an extra "Become Root" option in the menu.
This works similarly to the Linux "root" concept, in that if you become root,
you will be implicitly granted *all* permissions and nothing will be hidden
from you. This lasts until you "stop being root" or logout.

View file

@ -1,8 +1,8 @@
.. highlight:: sh
Documenting Your Project
========================
Document Your Project
=====================
At this point we assume you already have created a new project, and established
the Git repo for it etc.

62
pyproject.toml Normal file
View file

@ -0,0 +1,62 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "rattail-tutorial"
version = "0.3.1"
description = "Rattail Development Tutorial"
readme = "README.md"
authors = [{name = "Lance Edgar", email = "lance@edbob.org"}]
license = {text = "GNU GPL v3+"}
classifiers = [
"Development Status :: 3 - Alpha",
"Environment :: Console",
"Environment :: Web Environment",
"Framework :: Pyramid",
"Intended Audience :: Developers",
"Natural Language :: English",
"Operating System :: POSIX :: Linux",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Topic :: Office/Business",
]
dependencies = [
"furo",
"invoke",
"psycopg2",
"rattail[db,bouncer]",
"Sphinx",
"Tailbone",
"tox",
]
[project.scripts]
rattail_tutorial = "rattail_tutorial.commands:rattail_tutorial_typer"
[project.entry-points."paste.app_factory"]
main = "rattail_tutorial.web.app:main"
[project.entry-points."rattail.config.extensions"]
rattail_tutorial = "rattail_tutorial.config:RattailTutorialConfig"
[project.entry-points."rattail.emails"]
rattail_tutorial = "rattail_tutorial.emails"
[project.urls]
Homepage = "https://rattailproject.org"
repository = "https://forgejo.wuttaproject.org/rattail/rattail-tutorial"
Changelog = "https://forgejo.wuttaproject.org/rattail/rattail-tutorial/src/branch/master/CHANGELOG.md"
[tool.commitizen]
version_provider = "pep621"
tag_format = "v$version"
update_changelog_on_bump = true

View file

@ -1,3 +1,6 @@
# -*- coding: utf-8; -*-
__version__ = '0.1.0'
from importlib.metadata import version
__version__ = version('rattail-tutorial')

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2019 Lance Edgar
# Copyright © 2010-2024 Lance Edgar
#
# This file is part of Rattail.
#
@ -26,36 +26,22 @@ Rattail Tutorial commands
import sys
from rattail import commands
import typer
from rattail_tutorial import __version__
from rattail.commands.typer import make_typer
def main(*args):
"""
Main entry point for Rattail Tutorial command system
"""
args = list(args or sys.argv[1:])
cmd = Command()
cmd.run(*args)
rattail_tutorial_typer = make_typer(
name='rattail_tutorial',
help="Rattail Tutorial (custom Rattail system)"
)
class Command(commands.Command):
"""
Main command for Rattail Tutorial
"""
name = 'rattail_tutorial'
version = __version__
description = "Rattail Tutorial (custom Rattail system)"
long_description = ''
class HelloWorld(commands.Subcommand):
@rattail_tutorial_typer.command()
def hello(
ctx: typer.Context,
):
"""
The requisite 'hello world' example
"""
name = 'hello'
description = __doc__.strip()
def run(self, args):
self.stdout.write("hello world!\n")
sys.stdout.write("hello world!\n")

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2019 Lance Edgar
# Copyright © 2010-2024 Lance Edgar
#
# This file is part of Rattail.
#
@ -24,10 +24,10 @@
Custom config
"""
from rattail.config import ConfigExtension
from wuttjamaican.conf import WuttaConfigExtension
class Rattail_tutorialConfig(ConfigExtension):
class RattailTutorialConfig(WuttaConfigExtension):
"""
Rattail config extension for Rattail Tutorial
"""
@ -36,5 +36,4 @@ class Rattail_tutorialConfig(ConfigExtension):
def configure(self, config):
# set some default config values
config.setdefault('rattail.mail', 'emails', 'rattail_tutorial.emails')
config.setdefault('tailbone', 'menus', 'rattail_tutorial.web.menus')
config.setdefault('tailbone.menus.handler', 'rattail_tutorial.web.menus:TutorialMenuHandler')

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2019 Lance Edgar
# Copyright © 2010-2024 Lance Edgar
#
# This file is part of Rattail.
#
@ -26,9 +26,6 @@ Custom email profiles
from rattail.mail import Email
# bring in some common ones from rattail
from rattail.emails import datasync_error_watcher_get_changes, filemon_action_error
class rattail_import_sample_updates(Email):
"""

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2019 Lance Edgar
# Copyright © 2010-2024 Lance Edgar
#
# This file is part of Rattail.
#
@ -24,166 +24,139 @@
Web Menus
"""
from tailbone import menus as base
def simple_menus(request):
url = request.route_url
menus = [
{
class TutorialMenuHandler(base.MenuHandler):
"""
Demo menu handler
"""
def make_menus(self, request, **kwargs):
products_menu = self.make_products_menu(request)
vendors_menu = self.make_vendors_menu(request)
company_menu = self.make_company_menu(request)
batches_menu = self.make_batches_menu(request)
admin_menu = self.make_admin_menu(request,
include_stores=False,
include_tenders=False)
menus = [
products_menu,
vendors_menu,
company_menu,
batches_menu,
admin_menu,
]
return menus
def make_products_menu(self, request, **kwargs):
return {
'title': "Products",
'type': 'menu',
'items': [
{
'title': "Products",
'url': url('products'),
'route': 'products',
'perm': 'products.list',
},
{
'title': "Brands",
'url': url('brands'),
'route': 'brands',
'perm': 'brands.list',
},
{
'title': "Report Codes",
'url': url('reportcodes'),
'route': 'reportcodes',
'perm': 'reportcodes.list',
},
],
},
{
}
def make_vendors_menu(self, request, **kwargs):
return {
'title': "Vendors",
'type': 'menu',
'items': [
{
'title': "Vendors",
'url': url('vendors'),
'route': 'vendors',
'perm': 'vendors.list',
},
{'type': 'sep'},
{
'title': "Catalogs",
'url': url('vendorcatalogs'),
'route': 'vendorcatalogs',
'perm': 'vendorcatalogs.list',
},
{
'title': "Upload New Catalog",
'url': url('vendorcatalogs.create'),
'route': 'vendorcatalogs.create',
'perm': 'vendorcatalogs.create',
},
],
},
{
}
def make_company_menu(self, request, **kwargs):
return {
'title': "Company",
'type': 'menu',
'items': [
{
'title': "Stores",
'url': url('stores'),
'route': 'stores',
'perm': 'stores.list',
},
{
'title': "Departments",
'url': url('departments'),
'route': 'departments',
'perm': 'departments.list',
},
{
'title': "Subdepartments",
'url': url('subdepartments'),
'route': 'subdepartments',
'perm': 'subdepartments.list',
},
{'type': 'sep'},
{
'title': "Employees",
'url': url('employees'),
'route': 'employees',
'perm': 'employees.list',
},
{'type': 'sep'},
{
'title': "Customers",
'url': url('customers'),
'route': 'customers',
'perm': 'customers.list',
},
{
'title': "Customer Groups",
'url': url('customergroups'),
'route': 'customergroups',
'perm': 'customergroups.list',
},
],
},
{
}
def make_batches_menu(self, request, **kwargs):
return {
'title': "Batches",
'type': 'menu',
'items': [
{
'title': "Handheld",
'url': url('batch.handheld'),
'route': 'batch.handheld',
'perm': 'batch.handheld.list',
},
{
'title': "Inventory",
'url': url('batch.inventory'),
'route': 'batch.inventory',
'perm': 'batch.inventory.list',
},
],
},
{
'title': "Admin",
'type': 'menu',
'items': [
{
'title': "Users",
'url': url('users'),
'perm': 'users.list',
},
{
'title': "User Events",
'url': url('userevents'),
'perm': 'userevents.list',
},
{
'title': "Roles",
'url': url('roles'),
'perm': 'roles.list',
},
{'type': 'sep'},
{
'title': "App Settings",
'url': url('appsettings'),
'perm': 'settings.list',
},
{
'title': "Email Settings",
'url': url('emailprofiles'),
'perm': 'emailprofiles.list',
},
{
'title': "Email Attempts",
'url': url('email_attempts'),
'perm': 'email_attempts.list',
},
{
'title': "Raw Settings",
'url': url('settings'),
'perm': 'settings.list',
},
{'type': 'sep'},
{
'title': "DataSync Changes",
'url': url('datasyncchanges'),
'perm': 'datasync.list',
},
{
'title': "Tables",
'url': url('tables'),
'perm': 'tables.list',
},
{
'title': "Rattail Tutorial Upgrades",
'url': url('upgrades'),
'perm': 'upgrades.list',
},
],
},
]
return menus
}

View file

@ -1,14 +0,0 @@
## -*- coding: utf-8; mode: html; -*-
<%inherit file="tailbone:templates/home.mako" />
<%def name="title()">Home</%def>
<div class="logo">
## ${h.image(request.static_url('rattail_tutorial.web:static/img/rattail_tutorial.jpg'), "Rattail Tutorial Logo", id='logo', width=500)}
${h.image(request.static_url('tailbone:static/img/home_logo.png'), "Rattail Logo")}
</div>
<h1 style="text-align: center;">Welcome to Rattail Tutorial</h1>

View file

@ -1,18 +0,0 @@
## -*- coding: utf-8; mode: html; -*-
<%inherit file="tailbone:templates/login.mako" />
<%def name="extra_styles()">
${parent.extra_styles()}
<style type="text/css">
#logo {
margin: 40px auto;
}
</style>
</%def>
<%def name="logo()">
## ${h.image(request.static_url('ratbob.web:static/img/ratbob.jpg'), "Ratbob Logo", id='logo', width=500)}
${h.image(request.static_url('tailbone:static/img/home_logo.png'), "Rattail Logo", id='logo')}
</%def>
${parent.body()}

View file

@ -48,7 +48,6 @@ def includeme(config):
config.include('tailbone.views.reportcodes')
config.include('tailbone.views.roles')
config.include('tailbone.views.settings')
config.include('tailbone.views.shifts')
config.include('tailbone.views.stores')
config.include('tailbone.views.subdepartments')
config.include('tailbone.views.users')

118
setup.py
View file

@ -1,118 +0,0 @@
# -*- coding: utf-8; -*-
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2019 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 <http://www.gnu.org/licenses/>.
#
################################################################################
"""
Rattail Tutorial setup script
"""
import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
exec(open(os.path.join(here, 'rattail_tutorial', '_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
'psycopg2', # 2.6.2
'rattail[auth,db,bouncer]', # 0.7.25
'Tailbone', # 0.5.29
'tox', # 3.13.2
]
setup(
name = "rattail-tutorial",
version = __version__,
author = "Lance Edgar",
author_email = "lance@edbob.org",
url = "https://rattailproject.org",
license = "GNU GPL v3",
description = "Rattail Development Tutorial",
long_description = README,
classifiers = [
'Private :: Do Not Upload',
'Development Status :: 3 - Alpha',
'Environment :: Console',
'Environment :: Web Environment',
'Framework :: Pyramid',
'Intended Audience :: Developers',
'Natural Language :: English',
'Operating System :: POSIX :: Linux',
'Programming Language :: Python',
'Programming Language :: Python :: 2.7',
'Topic :: Office/Business',
],
install_requires = requires,
packages = find_packages(),
include_package_data = True,
entry_points = {
'rattail.config.extensions': [
'rattail_tutorial = rattail_tutorial.config:Rattail_tutorialConfig',
],
'console_scripts': [
'rattail_tutorial = rattail_tutorial.commands:main',
],
'rattail_tutorial.commands': [
'hello = rattail_tutorial.commands:HelloWorld',
],
'paste.app_factory': [
'main = rattail_tutorial.web.app:main',
],
},
)

38
tasks.py Normal file
View file

@ -0,0 +1,38 @@
# -*- coding: utf-8; -*-
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2024 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 <http://www.gnu.org/licenses/>.
#
################################################################################
"""
Tasks for 'rattail-tutorial' package
"""
from invoke import task
@task
def release(c):
"""
Release a new version of `rattail-tutorial`.
"""
c.run('rm -rf rattail_tutorial.egg-info')
c.run('rm -rf dist')
c.run('python -m build --sdist')
c.run('twine upload dist/*')