monopyly 1.4.7__py3-none-any.whl → 1.4.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
monopyly/CHANGELOG.md CHANGED
@@ -184,4 +184,12 @@
184
184
  - Refresh the table of transactions after making a payment on a credit card statement
185
185
  - Use SVG to handle long values in account/statement summary boxes; fixes bugs in page rendering (long value overflow) and hover actions not happening because of conflicting overlap with the sidebar
186
186
 
187
+
188
+ ### 1.4.8
189
+
190
+ - Set username collection to be case insensitive
191
+ - Use Flask/Gunicorn APIs (rather than subprocess CLI calls) to launch the app
192
+ - Fix bug in the ordering of balances in the bank account balance charts for transactions on duplicate dates
193
+
194
+
187
195
  <a name="bottom" id="bottom"></a>
monopyly/README.md CHANGED
@@ -22,7 +22,7 @@ To install the app, simply run
22
22
  $ pip install monopyly
23
23
  ```
24
24
 
25
- The package requires a recent version of Python (3.9+).
25
+ The package requires a recent version of Python (3.10+).
26
26
 
27
27
 
28
28
  ## Getting started
monopyly/__init__.py CHANGED
@@ -1,5 +1,5 @@
1
1
  """
2
- Run a development server for the Monopyly app.
2
+ Run the Monopyly app.
3
3
  """
4
4
 
5
5
  from flask import Flask
monopyly/_version.py CHANGED
@@ -1,4 +1,4 @@
1
1
  # file generated by setuptools_scm
2
2
  # don't change, don't track in version control
3
- __version__ = version = '1.4.7'
4
- __version_tuple__ = version_tuple = (1, 4, 7)
3
+ __version__ = version = '1.4.8'
4
+ __version_tuple__ = version_tuple = (1, 4, 8)
monopyly/auth/actions.py CHANGED
@@ -2,7 +2,12 @@
2
2
 
3
3
 
4
4
  def get_username_and_password(form):
5
- """Get username and password from a form."""
6
- username = form["username"]
5
+ """
6
+ Get username and password from a form.
7
+
8
+ Get the username and password from the given form. Username should
9
+ be case insensitive.
10
+ """
11
+ username = form["username"].lower()
7
12
  password = form["password"]
8
13
  return username, password
@@ -1,5 +1,7 @@
1
1
  """Module describing logical banking actions (to be used in routes)."""
2
2
 
3
+ from collections import UserList, namedtuple
4
+
3
5
  from ..common.utils import convert_date_to_midnight_timestamp
4
6
  from .accounts import BankAccountHandler, BankAccountTypeHandler
5
7
 
@@ -29,16 +31,55 @@ def get_balance_chart_data(transactions):
29
31
  Returns
30
32
  -------
31
33
  chart_data : list
32
- A list of sorted (x, y) pairs consisting of the Unix timestamp
33
- (in milliseconds) and the bank account balance.
34
+ A list containing (x, y) pairs, each consisting of the Unix
35
+ timestamp (in milliseconds) and the bank account balance.
36
+ """
37
+ return list(_BalanceChartData(transactions))
38
+
39
+
40
+ class _BalanceChartData(UserList):
34
41
  """
35
- chart_data = sorted(map(_make_transaction_balance_ordered_pair, transactions))
36
- return chart_data
42
+ A list of balances to be passed to a `chartist.js` chart constructor.
43
+
44
+ A special list-like object containing transaction data formatted for
45
+ use in a balance chart created by the `chartist.js` library. This
46
+ converts each transaction into an (x, y) pair consisting of a Unix
47
+ timestamp (in milleseconds) and a corresponding bank account
48
+ balance. For transactions occurring on the same day (the finest
49
+ granularity recorded by the Monopyly app), a slight offset is
50
+ added to each timestamp to guarantee a smooth representation in the
51
+ rendered chart.
52
+
53
+ Parameters
54
+ ----------
55
+ transactions : list
56
+ A list of transactions to be used for generating the chart data.
57
+ """
58
+
59
+ _DAILY_MILLISECONDS = 86_400_000
60
+ offset = 1
61
+ point = namedtuple("DataPoint", ["timestamp", "balance"])
62
+
63
+ def __init__(self, transactions):
64
+ super().__init__()
65
+ transaction_groups = self._group_transactions_by_date(transactions)
66
+ self._prepare_chart_data(transaction_groups)
37
67
 
68
+ @staticmethod
69
+ def _group_transactions_by_date(transactions):
70
+ date_groups = {}
71
+ for transaction in transactions:
72
+ group = date_groups.setdefault(transaction.transaction_date, [])
73
+ group.append(transaction)
74
+ return date_groups
38
75
 
39
- def _make_transaction_balance_ordered_pair(transaction):
40
- # Create an ordered pair of date (timestamp) and account balance
41
- timestamp = convert_date_to_midnight_timestamp(
42
- transaction.transaction_date, milliseconds=True
43
- )
44
- return timestamp, transaction.balance
76
+ def _prepare_chart_data(self, transaction_groups):
77
+ # Assign chart data to the list as tuples, adding offsets for duplicated dates
78
+ for transaction_date, transaction_group in transaction_groups.items():
79
+ base_timestamp = convert_date_to_midnight_timestamp(
80
+ transaction_date, milliseconds=True
81
+ )
82
+ offset = self._DAILY_MILLISECONDS / len(transaction_group)
83
+ for i, transaction in enumerate(transaction_group):
84
+ adjusted_timestamp = base_timestamp + (i * offset)
85
+ self.data.append((adjusted_timestamp, transaction.balance))
@@ -79,7 +79,8 @@ def load_account_details(account_id):
79
79
  "banking/account_page.html",
80
80
  account=account,
81
81
  account_transactions=transactions[:100],
82
- chart_data=get_balance_chart_data(transactions),
82
+ # Reverse the chart transactions to be chronologically ascending
83
+ chart_data=get_balance_chart_data(reversed(transactions)),
83
84
  )
84
85
 
85
86
 
monopyly/cli/apps.py CHANGED
@@ -21,25 +21,25 @@ class LocalApplication:
21
21
 
22
22
  mode_name = "local"
23
23
  default_port = "5001"
24
- command = ["flask"]
24
+ _debug = None
25
25
 
26
26
  def __init__(self, host=None, port=None, **options):
27
27
  """Initialize the application in development mode."""
28
28
  self._host = host
29
- self._port = port
29
+ self._port = port or self.default_port
30
30
  if options:
31
31
  raise NotImplementedError(
32
32
  f"Options besides `host` and `port` are not handled in {self.mode_name} mode."
33
33
  )
34
+ self.application = create_app()
34
35
 
35
36
  def run(self):
36
37
  """Run the Monopyly application in development mode."""
37
- instruction = self.command + ["run"]
38
- if self._host:
39
- instruction += ["--host", self._host]
40
- if self._port:
41
- instruction += ["--port", self._port]
42
- server = subprocess.Popen(instruction)
38
+ self.application.run(
39
+ host=self._host,
40
+ port=self._port,
41
+ debug=self._debug,
42
+ )
43
43
 
44
44
 
45
45
  class DevelopmentApplication(LocalApplication):
@@ -52,8 +52,8 @@ class DevelopmentApplication(LocalApplication):
52
52
  """
53
53
 
54
54
  mode_name = "development"
55
- default_port = "5000"
56
- command = LocalApplication.command + ["--debug"]
55
+ default_port = None # traditionally 5000
56
+ _debug = True
57
57
 
58
58
 
59
59
  class ProductionApplication(BaseApplication):
@@ -64,31 +64,33 @@ class ProductionApplication(BaseApplication):
64
64
  Gunicorn server instead of the built-in Python server.
65
65
  """
66
66
 
67
- default_port = "8000"
67
+ default_port = None # traditionally 8000
68
68
  _default_worker_count = (multiprocessing.cpu_count() * 2) + 1
69
69
 
70
70
  def __init__(self, host=None, port=None, **options):
71
71
  """Initialize the application in production mode."""
72
- options["bind"] = self._parse_binding(host, port, options.get("bind"))
73
- options.setdefault("workers", self._default_worker_count)
72
+ if port and not host:
73
+ raise ValueError("A host must be specified when the port is given.")
74
+ self._host = host
75
+ self._port = port or self.default_port
74
76
  self.options = options
77
+ self.options["bind"] = self._determine_binding(options.get("bind"))
78
+ self.options.setdefault("workers", self._default_worker_count)
75
79
  self.application = create_app()
76
80
  super().__init__()
77
81
 
78
- @staticmethod
79
- def _parse_binding(host, port, bind_option):
82
+ def _determine_binding(self, bind_option):
80
83
  # Parse any socket binding options
81
- if (host or port) and bind_option:
84
+ if self._host and bind_option:
82
85
  raise ValueError(
83
- "Neither `host` nor `port` parameters can be specified if the "
84
- "`bind` option is given."
86
+ "The `host` may not be specified directly if the `bind` option is used."
85
87
  )
86
- bind_values = []
87
- if host:
88
- bind_values.append(host)
89
- if port:
90
- bind_values.append(port)
91
- return bind if (bind := ":".join(bind_values)) else bind_option
88
+ if self._host:
89
+ bind_values = [self._host]
90
+ if self._port:
91
+ bind_values.append(self._port)
92
+ bind_option = ":".join(bind_values)
93
+ return bind_option
92
94
 
93
95
  def load_config(self):
94
96
  config = {
@@ -16,26 +16,34 @@ from rich.console import Console
16
16
 
17
17
  from .apps import DevelopmentApplication, LocalApplication, ProductionApplication
18
18
 
19
- # Set the Flask environment variable
20
- os.environ["FLASK_APP"] = "monopyly"
21
19
 
22
-
23
- def main():
24
- args = parse_arguments()
25
- app_launcher = Launcher(args.mode, host=args.host, port=args.port)
20
+ def main(mode, host=None, port=None, backup=False, browser=False):
21
+ app_launcher = Launcher(mode, host=host, port=port)
26
22
  # Initialize the database and run the app
27
23
  app_launcher.initialize_database()
28
- if args.backup:
24
+ if backup:
29
25
  app_launcher.backup_database()
30
26
  app_launcher.launch()
31
- if args.mode in ("development", "local"):
27
+ if mode in ("development", "local"):
32
28
  # Enable browser viewing in development mode
33
- if args.browser:
29
+ if browser:
34
30
  app_launcher.open_browser(delay=1)
35
31
  # Wait for the exit command to stop
36
32
  app_launcher.wait_for_exit()
37
33
 
38
34
 
35
+ def main_cli():
36
+ """Run the app as a command line program."""
37
+ args = parse_arguments()
38
+ main(
39
+ args.mode,
40
+ host=args.host,
41
+ port=args.port,
42
+ backup=args.backup,
43
+ browser=args.browser,
44
+ )
45
+
46
+
39
47
  def parse_arguments():
40
48
  parser = argparse.ArgumentParser(description=__doc__)
41
49
  parser.add_argument("--host", help="the host address where the app will be run")
@@ -121,4 +129,4 @@ class Launcher:
121
129
 
122
130
 
123
131
  if __name__ == "__main__":
124
- main()
132
+ main_cli()
@@ -123,6 +123,11 @@ header#masthead {
123
123
  filter: brightness(0.95);
124
124
  }
125
125
 
126
+ .monopyly-logo .development-mode {
127
+ font-weight: normal;
128
+ text-transform: none;
129
+ }
130
+
126
131
 
127
132
  /*
128
133
  * Display navigation links inline
@@ -10,36 +10,51 @@
10
10
 
11
11
  {% block content %}
12
12
  <div id="story" class="about">
13
- <p>It started with Microsoft Excel. </p>
14
- <p>When I got my first bank account, my dad taught me how to keep track of all my finances in an Excel workbook.
15
- It worked for a while, and as I acquired a handful of credit cards, investments, and other types of bank accounts, I kept adding sheets to that file.
16
- Of course, since I was tracking all that data, I wanted to wring as much information out of it as I possibly could—and so I started working rudimentary analytics into the spreadsheet.
13
+ <p>
14
+ It started with Microsoft Excel.
15
+ </p>
16
+ <p>
17
+ When I got my first bank account, my dad taught me how to keep track of all my finances in an Excel workbook.
18
+ It worked for a while, and as I acquired a handful of credit cards, investments, and other types of bank accounts, I kept adding sheets to that file.
19
+ Of course, since I was tracking all that data, I wanted to wring as much information out of it as I possibly could—and so I started working rudimentary analytics into the spreadsheet.
20
+ </p>
21
+
22
+ <p>
23
+ This all kept me satisfied until about halfway through college when I began learning Python.
24
+ Excel was getting cumbersome, and I wanted to be able to sort and tag types of transactions, link credit card payments with bank withdrawals, and create spending reports.
25
+ Seeing the potential ways I could use a standalone programming language to up my game, I realized that what I really needed was a database.
26
+ As I transitioned to graduate school, I also transitioned to tracking my finances in a MySQL database, accessed with Python through a set of Jupyter notebooks.
27
+ That approach gave me so much more power and flexibilty, but it still felt a little clunky.
28
+ </p>
29
+
30
+ <p>
31
+ My ideal situation?
32
+ </p>
33
+
34
+ <p>
35
+ I ultimately wanted a system that keep track of everything—credit card transactions, bank accounts, investments, retirement accounts, all that $—in one place.
36
+ Obviously there are mega-apps that already do all this, but I never wanted to go that route.
37
+ I'd always managed my finances independently, and had zero interest in ceding that control.
38
+ For one, I wanted to maintain some privacy regarding my financial data, because who knows how those apps are using that information.
39
+ Two, I didn't want <em>all</em> the bells and whistles (and advertisements) that those mega-apps would force upon me, but I also wanted something I could customize when I didn't like a feature... or when I wanted more.
40
+ And three, most importantly, it seemed like a fun challenge that would keep me deeply engaged in managing my own financial picture.
41
+ </p>
42
+
43
+ <p>
44
+ That's how this app came about.
45
+ I started by trying to just create a GUI for my Python database interface, but that didn't offer the graphic flexibility of a web app.
46
+ Why fight to build a nice Tkinter GUI if I'd eventually get sick of that too?
47
+ (Tkinter is also a bit of a pain to code, and a bigger pain to test, and <em>that</em> certainly wouldn't do.)
48
+ Anyway, I'd always wanted to create an app, and I figured this was as good a chance as any to get started.
49
+ Win-win.
17
50
  </p>
18
51
 
52
+ <p>
53
+ If you're reading this, I suppose it means you've stumbled across the program out of interest (or maybe you're just curious what the hell this nutjob is wasting his time on).
54
+ If the former, cool!
55
+ Feel free to look around or take it for a spin.
56
+ I intend to always keep the basic concept open source, so play around as much as you'd like!
19
57
  </p>
20
- This all kept me satisfied until about halfway through college when I began learning Python.
21
- Excel was getting cumbersome, and I wanted to be able to sort and tag types of transactions, link credit card payments with bank withdrawals, and create spending reports.
22
- Seeing the potential ways I could use a standalone programming language to up my game, I realized that what I really needed was a database.
23
- As I transitioned to graduate school, I also transitioned to tracking my finances in a MySQL database, accessed with Python through a set of Jupyter notebooks.
24
- That approach gave me so much more power and flexibilty, but it still felt a little clunky.</p>
25
-
26
- <p>My ideal situation?</p>
27
-
28
- <p>I ultimately wanted a system that keep track of everything—credit card transactions, bank accounts, investments, retirement accounts, all that $—in one place.
29
- Obviously there are mega-apps that already do all this, but I never wanted to go that route.
30
- I'd always managed my finances independently, and had zero interest in ceding that control.
31
- For one, I wanted to maintain some privacy regarding my financial data, because who knows how those apps are using that information.
32
- Two, I didn't want <em>all</em> the bells and whistles (and advertisements) that those mega-apps would force upon me, but I also wanted something I could customize when I didn't like a feature... or when I wanted more.
33
- And three, most importantly, it seemed like a fun challenge that would keep me deeply engaged in managing my own financial picture.
34
-
35
- <p>That's how this app came about.
36
- I started by trying to just create a GUI for my Python database interface, but that didn't offer the graphic flexibility of a web app.
37
- Why fight to build a nice Tkinter GUI if I'd eventually get sick of that too?
38
- (Tkinter is also a bit of a pain to code, and a bigger pain to test, and <em>that</em> certainly wouldn't do.)
39
- Anyway, I'd always wanted to create an app, and I figured this was as good a chance as any to get started.
40
- Win-win.</p>
41
-
42
- <p>If you're reading this, I suppose it means you've stumbled across the program out of interest (or maybe you're just curious what the hell this nutjob is wasting his time on). If the former, cool! Feel free to look around or take it for a spin. I intend to always keep the basic concept open source, so play around as much as you'd like!</p>
43
58
 
44
59
  <p class="signature">-Mitch</p>
45
60
  </div>
@@ -43,7 +43,12 @@
43
43
  <div class="container">
44
44
 
45
45
  <a href="{{ url_for('core.index') }}">
46
- <h1 class="monopyly-logo">Monopyly</h1>
46
+ <h1 class="monopyly-logo">
47
+ Monopyly
48
+ {%- if config['DEBUG'] -%}
49
+ <span class="development-mode">.dev</span>
50
+ {%- endif -%}
51
+ </h1>
47
52
  </a>
48
53
 
49
54
  <nav id="nav-menu">
@@ -52,7 +57,11 @@
52
57
  <li><a href="{{ url_for('core.index') }}">Home</a></li>
53
58
  <li><a href="{{ url_for('core.about') }}">About</a></li>
54
59
  {% if g.user %}
55
- <li><a href="{{url_for('core.load_profile') }}" class="username">{{ g.user.username }}</a></li>
60
+ <li>
61
+ <a href="{{url_for('core.load_profile') }}" class="username">
62
+ {{ g.user.username }}
63
+ </a>
64
+ </li>
56
65
  <li><a href="{{ url_for('auth.logout') }}">Log Out</a></li>
57
66
  {% else %}
58
67
  <li><a href="{{ url_for('auth.register') }}">Register</a></li>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: monopyly
3
- Version: 1.4.7
3
+ Version: 1.4.8
4
4
  Summary: A homemade personal finance manager.
5
5
  Project-URL: Download, https://pypi.org/project/monopyly
6
6
  Project-URL: Homepage, http://monopyly.com
@@ -58,7 +58,7 @@ To install the app, simply run
58
58
  $ pip install monopyly
59
59
  ```
60
60
 
61
- The package requires a recent version of Python (3.9+).
61
+ The package requires a recent version of Python (3.10+).
62
62
 
63
63
 
64
64
  ## Getting started
@@ -1,21 +1,21 @@
1
- monopyly/CHANGELOG.md,sha256=ulbbaPAcVSV7oNWm3yswxZJFCESWwG2zk2jamVJxAFQ,7137
2
- monopyly/README.md,sha256=f7pDaNKl5hvycxVWWuZOeO6SDP-qI4BafgvyZwPPoVE,9027
3
- monopyly/__init__.py,sha256=5ImOjkZGxUBhqG4EK5YWebwTO4V8G2fa_lZAGCD5SgY,2207
4
- monopyly/_version.py,sha256=nmlXCBuHHFy5JdYfw3oylepRJ5P5EEImr1ItrcZvJdo,160
5
- monopyly/auth/actions.py,sha256=T99eAP8dxFZMzLu2LxZFIXGYIroP8I7KJ-WJ8GJ1gws,260
1
+ monopyly/CHANGELOG.md,sha256=1IibmFq7TR7cIAVhFhCRKKQPdn9-bzBwmY5EhTsp2pA,7388
2
+ monopyly/README.md,sha256=cm1wli7E-xybYoJr-tsrNgfIO6TPrLsraMUSO26D6xk,9028
3
+ monopyly/__init__.py,sha256=1EYKyyHgORJ4Zh-3AB5R3AuLS0mqREwN1-iPDrZZUZs,2182
4
+ monopyly/_version.py,sha256=o7K855LfRl1a6KN9ryI52BaWntUGitBJboNncGT-QCk,160
5
+ monopyly/auth/actions.py,sha256=zFDb_EATufsJMzQ4rX0bzlme8e62mXFpYtQvc_k0jEc,375
6
6
  monopyly/auth/blueprint.py,sha256=sFbmTvSBhjv1pn2gJLH5J6zanPLuemmWbgEj5ZKCiTY,244
7
7
  monopyly/auth/routes.py,sha256=mODJHrdFhffusfbYwQ_wpIY7eAE7Gh7irosIef4Mluc,2902
8
8
  monopyly/auth/tools.py,sha256=hifCHBN06Ht-FnMhJPzzj-xjMN8uwbeJ-azRVjnT99c,801
9
9
  monopyly/banking/accounts.py,sha256=yYlXvyhLBQoBZYr_WMk6_3nxlhwU4NEkCYKv5hHFjcM,9828
10
- monopyly/banking/actions.py,sha256=am8AlVWJGhrTvWNiAQPba-2guxdESmhzl6mIJhjAmlg,1565
10
+ monopyly/banking/actions.py,sha256=NvButozWJNRuNIiyM-Gy88XLTpIjNcEGSQcLMfEwOUg,3258
11
11
  monopyly/banking/banks.py,sha256=X1seKJrec-o8z-bM0wVTR42vMx1q5A9Lf2jNUtINlrQ,1745
12
12
  monopyly/banking/blueprint.py,sha256=PDsqe4DmiT7cDYW9IxxTfizu9Lqol1Lhp7ajMK6fUuI,255
13
13
  monopyly/banking/filters.py,sha256=wCsAUh592B5BmGFC9NqmrJZ0NdQZi21hvy0QsKqhgLg,685
14
14
  monopyly/banking/forms.py,sha256=p-YGZgdKugk3VKILLiQNEH5KQmXop5G8P1Bs4sUqbK0,10506
15
- monopyly/banking/routes.py,sha256=BAV6PBQf20dSTxqY88Zh0FGAzpj7TxgZaHPxGCJneJ4,8149
15
+ monopyly/banking/routes.py,sha256=mykWVtV_4f096-NWDWE5aPYoBvGjeNpBSyY9Kb_nQGc,8232
16
16
  monopyly/banking/transactions.py,sha256=2_wFXl4ZrHzLoFGz72ksYA2_8UvB0N1wtBFd8kTwTyQ,8454
17
- monopyly/cli/apps.py,sha256=TY97lShiJmsKAnVXVbBLJDXW2TmiyNwrPic8w9roPCQ,3356
18
- monopyly/cli/run.py,sha256=8NHv5TW5Ze6pyhxZCOjmba-EU4Nu6sObYfNJbDPtrds,3838
17
+ monopyly/cli/apps.py,sha256=v5l8eOvQddJc-Y3B3d-1xwSJcPMb-QyqbcGxZjlYczQ,3442
18
+ monopyly/cli/launch.py,sha256=UszkXSDh1SDEZNK2utLpnEK1rRPJ3iamNuulxxmyXLU,4000
19
19
  monopyly/common/transactions.py,sha256=2-EkctGC9k5W5kodXdYJIBXu5l5JNI9dxfgbp2Nxccg,12185
20
20
  monopyly/common/utils.py,sha256=BjXhfNXGWkAPt-ebldvmZ2z00P8MhKJzjxrJJ6mzRQY,5867
21
21
  monopyly/common/forms/__init__.py,sha256=6iFTlcoaQmCbrjS1KfFhWXQUfyqnA-vKPMVxLyJMlXY,120
@@ -48,7 +48,7 @@ monopyly/database/preloads.sql,sha256=KBS_WYRofFdOVN-IgHzZhfyJrY6ZOwHeExN-fQr3ht
48
48
  monopyly/database/schema.sql,sha256=cdl9b5CnYrnQ-lck147GtwArx_JJbX1vF9YYLivTeyw,4660
49
49
  monopyly/database/views.sql,sha256=UTO2QRkVTfQ12bMVkR-O6Qv80DvYo8hngPHn2A1_1F8,3853
50
50
  monopyly/static/jquery-3.7.0.min.js,sha256=2Pmvv0kuTBOenSvLm6bvfBSSHrUJ-3A7x6P5Ebd07_g,87462
51
- monopyly/static/css/style.css,sha256=czs8-2XXHEWUNfO5MQ-AdvpfHHZzq6P7jR0BRnknZ1E,50618
51
+ monopyly/static/css/style.css,sha256=cmehDMaKF9uJB6ZjAcq81C3SnQx3sJxMUeDbWbl1gRI,50703
52
52
  monopyly/static/favicon/browserconfig.xml,sha256=Zt_AVOxiritWWXoUwPsHpx4vu4kM_butdFVzoYCYbM8,315
53
53
  monopyly/static/favicon/favicon-114.png,sha256=kjElVFiix-kFCMdADkLpJsi8kL3GDsFm85oJhyCH-C0,20601
54
54
  monopyly/static/favicon/favicon-120.png,sha256=g4uzHMdW0MlJhcgWfrOsj2MB2D-HdLa4t60_hvyICkM,22077
@@ -138,7 +138,7 @@ monopyly/static/js/modules/manage-overlays.js,sha256=gCE1qTT_0RG6a5OX9PrFOc-KLmq
138
138
  monopyly/static/js/modules/manage-subforms.js,sha256=-yKA7l8ZI0294auTI307LrKkw_Bl6I8suwK4VLuLhMc,2197
139
139
  monopyly/static/js/modules/update-database-widget.js,sha256=S67hmqaGwzbPy94IjYrag0ZPOur4r5y_tb3_5t7xuYI,1581
140
140
  monopyly/static/js/modules/update-display-ajax.js,sha256=MJBiRMmeIHRG7lLbqIcXkUecKNNMFFVJXwhs_N8LKl0,878
141
- monopyly/templates/layout.html,sha256=ETQ7fNC4H0JjZZTnamZoJKwXbsXEHW72ZhahOER3NkQ,4741
141
+ monopyly/templates/layout.html,sha256=AOlElsehSKBKnejYWZfn33jA04lGrViP_NcNF24vI7U,4955
142
142
  monopyly/templates/auth/login.html,sha256=aZwaHBiKtQa_ZkVBqLUQIbwQdEAJNwcyYNjFQcRp-k0,443
143
143
  monopyly/templates/auth/register.html,sha256=G6VxfYPIbXQco6Z_1PVQQ40vNWgG3PScmN20npx88yQ,447
144
144
  monopyly/templates/banking/account_page.html,sha256=pP7j6pRngqO8D_kQKbRINTQ61L5VJs66dsNPscO0czs,1946
@@ -172,7 +172,7 @@ monopyly/templates/common/transactions_table/transactions.html,sha256=pwJxOPZgU7
172
172
  monopyly/templates/core/credits.html,sha256=uXkDl6XwsZAu1weONQQlf1WiBUZDiTHqsZLkvu6JAXU,948
173
173
  monopyly/templates/core/index.html,sha256=caoQuizzJibU90nivf1-Esnptg5wzFWyhVJoAkEPKdE,4374
174
174
  monopyly/templates/core/profile.html,sha256=88DgHlnSAZ9V4pAJmo_kPpRRY_1vhwcrYLxS5hZJDxM,2356
175
- monopyly/templates/core/story.html,sha256=fUvIE8t5oG_Mw443Oeu4vWKospFQv8dSfBOCisn5L0g,3207
175
+ monopyly/templates/core/story.html,sha256=iEKfX1aHxXrstAeeQ6J8Gnvg1zGt95c-iLELUhG-AtE,3331
176
176
  monopyly/templates/core/errors/400.html,sha256=whUYO3b6UIQWfN8y563umccU8GLxqXu0A5nb5uNM-XY,152
177
177
  monopyly/templates/core/errors/401.html,sha256=3HH9TSDZfhyxZVcVnT0PNe524ADvEHIj6BsllQYFFOQ,154
178
178
  monopyly/templates/core/errors/403.html,sha256=SSJsDIKFFKqap5RR4oM7IsvWY6dsgfZVPPKPSpB2d6A,155
@@ -209,9 +209,9 @@ monopyly/templates/credit/transactions_table/condensed_row_content.html,sha256=T
209
209
  monopyly/templates/credit/transactions_table/expanded_row_content.html,sha256=oL1BqlEC3H6s3fSI9Vb65DLL-P9OPliPqqiGL4av4Xs,1971
210
210
  monopyly/templates/credit/transactions_table/transaction_field_titles.html,sha256=km-3YEDJaygwcKV-rwYnrE7xF8u4Z7jCBsk0Ia-LO-M,758
211
211
  monopyly/templates/credit/transactions_table/transactions.html,sha256=tcppv0qNV-Qq6U5jfxoNyGKPXmyV9h9nR6rw4jXfBsY,481
212
- monopyly-1.4.7.dist-info/METADATA,sha256=7ZTOH0Fw5UhAhzb4MzeGdUNYpljWSnWYE3f1kTxSM9o,10952
213
- monopyly-1.4.7.dist-info/WHEEL,sha256=Fd6mP6ydyRguakwUJ05oBE7fh2IPxgtDN9IwHJ9OqJQ,87
214
- monopyly-1.4.7.dist-info/entry_points.txt,sha256=ANAwWNF6IG83opRITM2P9i_im_b6qLdG1n7dAcS2ZNU,51
215
- monopyly-1.4.7.dist-info/licenses/COPYING,sha256=5X8cMguM-HmKfS_4Om-eBqM6A1hfbgZf6pfx2G24QFI,35150
216
- monopyly-1.4.7.dist-info/licenses/LICENSE,sha256=94rIicMccmTPhqXiRLV9JsU8P2ocMuEUUtUpp6LPKiE,253
217
- monopyly-1.4.7.dist-info/RECORD,,
212
+ monopyly-1.4.8.dist-info/METADATA,sha256=y9TCCzprVzIUZ1OEGpkqQk9issz0EzhDKbaoM8xCT04,10953
213
+ monopyly-1.4.8.dist-info/WHEEL,sha256=Fd6mP6ydyRguakwUJ05oBE7fh2IPxgtDN9IwHJ9OqJQ,87
214
+ monopyly-1.4.8.dist-info/entry_points.txt,sha256=_GmCja7NEqYHlGlVbz4rThqk0SIOmFUkiE8mN1dwgdY,58
215
+ monopyly-1.4.8.dist-info/licenses/COPYING,sha256=5X8cMguM-HmKfS_4Om-eBqM6A1hfbgZf6pfx2G24QFI,35150
216
+ monopyly-1.4.8.dist-info/licenses/LICENSE,sha256=94rIicMccmTPhqXiRLV9JsU8P2ocMuEUUtUpp6LPKiE,253
217
+ monopyly-1.4.8.dist-info/RECORD,,
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ monopyly = monopyly.cli.launch:main_cli
@@ -1,2 +0,0 @@
1
- [console_scripts]
2
- monopyly = monopyly.cli.run:main