Compare commits

...

23 commits

Author SHA1 Message Date
Lance Edgar b2113bcd88 docs: use markdown for readme file 2024-09-13 18:34:46 -05:00
Lance Edgar 860355f8af fix: avoid deprecated base class for config extension 2024-08-16 10:12:47 -05:00
Lance Edgar 3591b7e317 bump: version 0.3.2 → 0.3.3 2024-07-05 10:08:20 -05:00
Lance Edgar ec3fd0b2fb fix: define host_key for MailChimp -> Rattail import 2024-07-05 10:08:00 -05:00
Lance Edgar 4f618e80ca bump: version 0.3.1 → 0.3.2 2024-07-01 15:11:51 -05:00
Lance Edgar 42cddaf6c0 fix: remove legacy command definitions 2024-07-01 12:27:07 -05:00
Lance Edgar ac6efbb589 bump: version 0.3.0 → 0.3.1 2024-06-14 17:31:52 -05:00
Lance Edgar 39193bb27b fix: fallback to importlib_metadata on older python 2024-06-14 17:30:53 -05:00
Lance Edgar f5b24562b4 bump: version 0.2.1 → 0.3.0 2024-06-10 22:04:19 -05:00
Lance Edgar 7089ced72b feat: switch from setup.cfg to pyproject.toml + hatchling 2024-06-10 22:04:05 -05:00
Lance Edgar 2ab7cf04c6 Update changelog 2024-06-04 17:22:10 -05:00
Lance Edgar 6757a48c34 Setup default handler for Mailchimp -> Rattail import 2024-06-04 17:21:30 -05:00
Lance Edgar 48c8ea43df Fix default dist filename for release task
not sure why this fix was needed, did setuptools behavior change?
2024-06-03 11:22:47 -05:00
Lance Edgar 1a4991d9c4 Update changelog 2024-06-03 11:21:46 -05:00
Lance Edgar 6ee6d5fea8 Add typer equivalents for rattail commands 2024-05-16 20:04:52 -05:00
Lance Edgar a80edf160b Update changelog 2023-11-30 22:22:58 -06:00
Lance Edgar fad83c465f Update subcommand entry point group names, per wuttjamaican 2023-11-30 22:22:33 -06:00
Lance Edgar 8447b63641 Update changelog 2023-06-01 14:25:13 -05:00
Lance Edgar cdea5067c0 Replace setup.py contents with setup.cfg 2023-05-16 14:28:31 -05:00
Lance Edgar e9dbc1d814 Update changelog 2023-05-13 17:49:21 -05:00
Lance Edgar b0c197e4b2 Avoid deprecated import for OrderedDict 2023-05-05 01:54:13 -05:00
Lance Edgar a343692c6c Update changelog 2023-02-21 19:21:34 -06:00
Lance Edgar c03119acb2 Tweak ORM relationship backrefs per SA 2.0 warnings 2023-02-21 18:15:27 -06:00
12 changed files with 218 additions and 158 deletions

3
.gitignore vendored
View file

@ -1 +1,4 @@
*~
*.pyc
dist/
rattail_mailchimp.egg-info/ rattail_mailchimp.egg-info/

View file

@ -5,6 +5,54 @@ All notable changes to rattail-mailchimp will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) 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). and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## v0.3.3 (2024-07-05)
### Fix
- define `host_key` for MailChimp -> Rattail import
## v0.3.2 (2024-07-01)
### Fix
- remove legacy command definitions
## v0.3.1 (2024-06-14)
### Fix
- fallback to `importlib_metadata` on older python
## v0.3.0 (2024-06-10)
### Feat
- switch from setup.cfg to pyproject.toml + hatchling
## [0.2.1] - 2024-06-04
### Changed
- Setup default handler for Mailchimp -> Rattail import.
## [0.2.0] - 2024-06-03
### Changed
- Migrate all commands to use `typer`.
## [0.1.5] - 2023-11-30
### Changed
- Update subcommand entry point group names, per wuttjamaican.
## [0.1.4] - 2023-06-01
### Changed
- Replace `setup.py` contents with `setup.cfg`.
## [0.1.3] - 2023-05-13
### Changed
- Avoid deprecated import for `OrderedDict`.
## [0.1.2] - 2023-02-21
### Changed
- Tweak ORM relationship backrefs per SA 2.0 warnings.
## [0.1.1] - 2022-08-06 ## [0.1.1] - 2022-08-06
### Changed ### Changed
- Register email profiles provided by this pkg. - Register email profiles provided by this pkg.

11
README.md Normal file
View file

@ -0,0 +1,11 @@
# rattail_mailchimp
Rattail is a retail software framework, released under the GNU General
Public License.
This package contains software interfaces for the
[MailChimp](https://mailchimp.com/) system.
Please see the [Rattail Project](https://rattailproject.org/) for more
information.

View file

@ -1,14 +0,0 @@
rattail_mailchimp
=================
Rattail is a retail software framework, released under the GNU General
Public License.
This package contains software interfaces for the `MailChimp`_ system.
.. _`MailChimp`: https://mailchimp.com/
Please see the `Rattail Project`_ for more information.
.. _`Rattail Project`: https://rattailproject.org/

54
pyproject.toml Normal file
View file

@ -0,0 +1,54 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "rattail-mailchimp"
version = "0.3.3"
description = "Rattail Software Interfaces for MailChimp"
readme = "README.md"
authors = [{name = "Lance Edgar", email = "lance@edbob.org"}]
license = {text = "GNU GPL v3+"}
classifiers = [
"Development Status :: 4 - Beta",
"Environment :: Console",
"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 = [
"mailchimp3",
"rattail",
]
[project.entry-points."rattail.config.extensions"]
rattail_mailchimp = "rattail_mailchimp.config:MailchimpConfigExtension"
[project.entry-points."rattail.typer_imports"]
rattail_mailchimp = "rattail_mailchimp.commands"
[project.entry-points."rattail.emails"]
rattail_mailchimp = "rattail_mailchimp.emails"
[project.urls]
Homepage = "https://rattailproject.org"
Repository = "https://kallithea.rattailproject.org/rattail-project/rattail-mailchimp"
Changelog = "https://kallithea.rattailproject.org/rattail-project/rattail-mailchimp/files/master/CHANGELOG.md"
[tool.commitizen]
version_provider = "pep621"
tag_format = "v$version"
update_changelog_on_bump = true

View file

@ -1,3 +1,9 @@
# -*- coding: utf-8; -*- # -*- coding: utf-8; -*-
__version__ = '0.1.1' try:
from importlib.metadata import version
except ImportError:
from importlib_metadata import version
__version__ = version('rattail-mailchimp')

View file

@ -2,7 +2,7 @@
################################################################################ ################################################################################
# #
# Rattail -- Retail Software Framework # Rattail -- Retail Software Framework
# Copyright © 2010-2021 Lance Edgar # Copyright © 2010-2024 Lance Edgar
# #
# This file is part of Rattail. # This file is part of Rattail.
# #
@ -24,23 +24,25 @@
Rattail Commands for MailChimp integration Rattail Commands for MailChimp integration
""" """
from rattail import commands import typer
from rattail.util import load_object
from rattail.commands import rattail_typer
from rattail.commands.typer import importer_command, typer_get_runas_user
from rattail.commands.importing import ImportCommandHandler
class ImportMailChimp(commands.ImportSubcommand): @rattail_typer.command()
@importer_command
def import_mailchimp(
ctx: typer.Context,
**kwargs
):
""" """
Import data to Rattail, from MailChimp API Import data to Rattail, from MailChimp API
""" """
name = 'import-mailchimp' config = ctx.parent.rattail_config
description = __doc__.strip() progress = ctx.parent.rattail_progress
default_handler_spec = 'rattail_mailchimp.importing.mailchimp:FromMailChimpToRattail' handler = ImportCommandHandler(
config, import_handler_key='to_rattail.from_mailchimp.import')
def get_handler_factory(self, **kwargs): kwargs['user'] = typer_get_runas_user(ctx)
if self.config: handler.run(kwargs, progress=progress)
spec = self.config.get('rattail.importing', 'mailchimp.handler',
default=self.default_handler_spec)
else:
# just use default, for sake of cmd line help
spec = self.default_handler_spec
return load_object(spec)

View file

@ -0,0 +1,42 @@
# -*- 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/>.
#
################################################################################
"""
Config extensions for rattail-mailchimp
"""
from wuttjamaican.conf import WuttaConfigExtension
class MailchimpConfigExtension(WuttaConfigExtension):
"""
Config extension for rattail-mailchimp
"""
key = 'rattail_mailchimp'
def configure(self, config):
# rattail import-mailchimp
config.setdefault('rattail.importing', 'to_rattail.from_mailchimp.import.default_handler',
'rattail_mailchimp.importing.mailchimp:FromMailChimpToRattail')
config.setdefault('rattail.importing', 'to_rattail.from_mailchimp.import.default_cmd',
'rattail import-mailchimp')

View file

@ -2,7 +2,7 @@
################################################################################ ################################################################################
# #
# Rattail -- Retail Software Framework # Rattail -- Retail Software Framework
# Copyright © 2010-2021 Lance Edgar # Copyright © 2010-2023 Lance Edgar
# #
# This file is part of Rattail. # This file is part of Rattail.
# #
@ -45,6 +45,11 @@ class MailChimpList(model.Base):
date_created = sa.Column(sa.DateTime(), nullable=True) date_created = sa.Column(sa.DateTime(), nullable=True)
members = orm.relationship('MailChimpListMember',
back_populates='list',
# nb. this is to satisfy SA 2.0
cascade_backrefs=False)
def __str__(self): def __str__(self):
return self.name or "" return self.name or ""
@ -62,7 +67,8 @@ class MailChimpListMember(model.Base):
uuid = model.uuid_column() uuid = model.uuid_column()
list_uuid = sa.Column(sa.String(length=32), nullable=False) list_uuid = sa.Column(sa.String(length=32), nullable=False)
list = orm.relationship(MailChimpList, backref='members') list = orm.relationship(MailChimpList,
back_populates='members')
id = sa.Column(sa.String(length=32), nullable=True) id = sa.Column(sa.String(length=32), nullable=True)

View file

@ -2,7 +2,7 @@
################################################################################ ################################################################################
# #
# Rattail -- Retail Software Framework # Rattail -- Retail Software Framework
# Copyright © 2010-2021 Lance Edgar # Copyright © 2010-2024 Lance Edgar
# #
# This file is part of Rattail. # This file is part of Rattail.
# #
@ -25,12 +25,11 @@ MailChimp -> Rattail "cache" data import
""" """
import datetime import datetime
from collections import OrderedDict
from mailchimp3 import MailChimp from mailchimp3 import MailChimp
from rattail import importing from rattail import importing
from rattail.util import OrderedDict
from rattail.time import localtime, make_utc
from rattail_mailchimp import importing as mailchimp_importing from rattail_mailchimp import importing as mailchimp_importing
@ -38,7 +37,9 @@ class FromMailChimpToRattail(importing.ToRattailHandler):
""" """
Handler for MailChimp -> Rattail cache import Handler for MailChimp -> Rattail cache import
""" """
host_key = 'mailchimp'
host_title = "MailChimp" host_title = "MailChimp"
generic_host_title = "MailChimp"
def get_importers(self): def get_importers(self):
importers = OrderedDict() importers = OrderedDict()
@ -53,7 +54,7 @@ class FromMailChimp(importing.Importer):
""" """
def setup(self): def setup(self):
super(FromMailChimp, self).setup() super().setup()
self.api_key = self.config.require('mailchimp', 'api_key') self.api_key = self.config.require('mailchimp', 'api_key')
self.mailchimp = MailChimp(self.api_key) self.mailchimp = MailChimp(self.api_key)
@ -65,10 +66,10 @@ class FromMailChimp(importing.Importer):
# issue..since we clearly have a UTC value # issue..since we clearly have a UTC value
value = value[:-6] value = value[:-6]
dt = datetime.datetime.strptime(value, '%Y-%m-%dT%H:%M:%S') dt = datetime.datetime.strptime(value, '%Y-%m-%dT%H:%M:%S')
dt = localtime(self.config, dt, from_utc=True) dt = self.app.localtime(dt, from_utc=True)
else: else:
dt = datetime.datetime.strptime(value, '%Y-%m-%dT%H:%M:%S%z') dt = datetime.datetime.strptime(value, '%Y-%m-%dT%H:%M:%S%z')
dt = localtime(self.config, dt) dt = self.app.localtime(dt)
return dt return dt
@ -95,7 +96,7 @@ class MailChimpListImporter(FromMailChimp, mailchimp_importing.model.MailChimpLi
return { return {
'id': mclist['id'], 'id': mclist['id'],
'name': mclist['name'], 'name': mclist['name'],
'date_created': make_utc(date_created), 'date_created': self.app.make_utc(date_created),
} }
@ -130,10 +131,20 @@ class MailChimpListMemberImporter(FromMailChimp, mailchimp_importing.model.MailC
def get_all_members(self, list_id): def get_all_members(self, list_id):
members = [] members = []
# cf. https://mailchimp.com/developer/marketing/api/list-members/list-members-info/
result = self.mailchimp.lists.members.all(list_id, get_all=True, result = self.mailchimp.lists.members.all(list_id, get_all=True,
# TODO: maybe should try this instead of # TODO: maybe should try this instead of
# the default which seems to be 500 # the default which seems to be 500
# count=1000 # count=1000
# TODO: this testing chunk left here for
# reference; it can be handy to filter
# results etc. for test runs
# count=500,
# # since_last_changed=datetime.date(2023, 1, 1),
# sort_field='last_changed',
# sort_dir='DESC',
) )
members.extend(result['members']) members.extend(result['members'])
return members return members
@ -150,6 +161,6 @@ class MailChimpListMemberImporter(FromMailChimp, mailchimp_importing.model.MailC
'status': member['status'], 'status': member['status'],
# TODO: this API endpoint does not appear to include this field? # TODO: this API endpoint does not appear to include this field?
# 'unsubscribe_reason': member.get('unsubscribe_reason'), # 'unsubscribe_reason': member.get('unsubscribe_reason'),
'last_changed': make_utc(last_changed), 'last_changed': self.app.make_utc(last_changed),
'source': member['source'], 'source': member['source'],
} }

107
setup.py
View file

@ -1,107 +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 <http://www.gnu.org/licenses/>.
#
################################################################################
import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
exec(open(os.path.join(here, 'rattail_mailchimp', '_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
'mailchimp3', # 3.0.14
'rattail', # 0.9.214
]
setup(
name = "rattail-mailchimp",
version = __version__,
author = "Lance Edgar",
author_email = "lance@edbob.org",
url = "https://rattailproject.org/",
license = "GNU GPL v3",
description = "Rattail Software Interfaces for MailChimp",
long_description = README,
classifiers = [
'Development Status :: 4 - Beta',
'Environment :: Console',
'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,
entry_points = {
'rattail.commands': [
'import-mailchimp = rattail_mailchimp.commands:ImportMailChimp',
],
'rattail.emails': [
'rattail_mailchimp = rattail_mailchimp.emails',
],
},
)

View file

@ -2,7 +2,7 @@
################################################################################ ################################################################################
# #
# Rattail -- Retail Software Framework # Rattail -- Retail Software Framework
# Copyright © 2010-2022 Lance Edgar # Copyright © 2010-2024 Lance Edgar
# #
# This file is part of Rattail. # This file is part of Rattail.
# #
@ -30,17 +30,15 @@ import shutil
from invoke import task from invoke import task
here = os.path.abspath(os.path.dirname(__file__))
exec(open(os.path.join(here, 'rattail_mailchimp', '_version.py')).read())
@task @task
def release(ctx): def release(c):
""" """
Release a new version of 'rattail-mailchimp'. Release a new version of 'rattail-mailchimp'.
""" """
shutil.rmtree('rattail_mailchimp.egg-info') if os.path.exists('dist'):
ctx.run('python -m build --sdist') shutil.rmtree('dist')
if os.path.exists('rattail_mailchimp.egg-info'):
shutil.rmtree('rattail_mailchimp.egg-info')
c.run('python -m build --sdist')
filename = 'rattail-mailchimp-{}.tar.gz'.format(__version__) c.run('twine upload dist/*')
ctx.run('twine upload dist/{}'.format(filename))