summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--python-business-rules.spec742
-rw-r--r--sources1
3 files changed, 744 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index e69de29..2f012a8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -0,0 +1 @@
+/business-rules-1.1.1.tar.gz
diff --git a/python-business-rules.spec b/python-business-rules.spec
new file mode 100644
index 0000000..a9bbc48
--- /dev/null
+++ b/python-business-rules.spec
@@ -0,0 +1,742 @@
+%global _empty_manifest_terminate_build 0
+Name: python-business-rules
+Version: 1.1.1
+Release: 1
+Summary: Python DSL for setting up business intelligence rules that can be configured without code
+License: MIT
+URL: https://github.com/venmo/business-rules
+Source0: https://mirrors.nju.edu.cn/pypi/web/packages/40/d2/3dc665d80fc71228b78282113d2a2577bab4f7ae2f46b8eb61d73902ad30/business-rules-1.1.1.tar.gz
+BuildArch: noarch
+
+Requires: python3-six
+
+%description
+As a software system grows in complexity and usage, it can become burdensome if
+every change to the logic/behavior of the system also requires you to write and
+deploy new code. The goal of this business rules engine is to provide a simple
+interface allowing anyone to capture new rules and logic defining the behavior
+of a system, and a way to then process those rules on the backend.
+You might, for example, find this is a useful way for analysts to define
+marketing logic around when certain customers or items are eligible for a
+discount or to automate emails after users enter a certain state or go through
+a particular sequence of events.
+## Usage
+### 1. Define Your set of variables
+Variables represent values in your system, usually the value of some particular object. You create rules by setting threshold conditions such that when a variable is computed that triggers the condition some action is taken.
+You define all the available variables for a certain kind of object in your code, and then later dynamically set the conditions and thresholds for those.
+For example:
+```python
+class ProductVariables(BaseVariables):
+ def __init__(self, product):
+ self.product = product
+ @numeric_rule_variable
+ def current_inventory(self):
+ return self.product.current_inventory
+ @numeric_rule_variable(label='Days until expiration')
+ def expiration_days(self)
+ last_order = self.product.orders[-1]
+ return (last_order.expiration_date - datetime.date.today()).days
+ @string_rule_variable()
+ def current_month(self):
+ return datetime.datetime.now().strftime("%B")
+ @select_rule_variable(options=Products.top_holiday_items())
+ def goes_well_with(self):
+ return products.related_products
+```
+### 2. Define your set of actions
+These are the actions that are available to be taken when a condition is triggered.
+For example:
+```python
+class ProductActions(BaseActions):
+ def __init__(self, product):
+ self.product = product
+ @rule_action(params={"sale_percentage": FIELD_NUMERIC})
+ def put_on_sale(self, sale_percentage):
+ self.product.price = (1.0 - sale_percentage) * self.product.price
+ self.product.save()
+ @rule_action(params={"number_to_order": FIELD_NUMERIC})
+ def order_more(self, number_to_order):
+ ProductOrder.objects.create(product_id=self.product.id,
+ quantity=number_to_order)
+```
+If you need a select field for an action parameter, another -more verbose- syntax is available:
+```python
+class ProductActions(BaseActions):
+ def __init__(self, product):
+ self.product = product
+ @rule_action(params=[{'fieldType': FIELD_SELECT,
+ 'name': 'stock_state',
+ 'label': 'Stock state',
+ 'options': [
+ {'label': 'Available', 'name': 'available'},
+ {'label': 'Last items', 'name': 'last_items'},
+ {'label': 'Out of stock', 'name': 'out_of_stock'}
+ ]}])
+ def change_stock_state(self, stock_state):
+ self.product.stock_state = stock_state
+ self.product.save()
+```
+### 3. Build the rules
+A rule is just a JSON object that gets interpreted by the business-rules engine.
+Note that the JSON is expected to be auto-generated by a UI, which makes it simple for anyone to set and tweak business rules without knowing anything about the code. The javascript library used for generating these on the web can be found [here](https://github.com/venmo/business-rules-ui).
+An example of the resulting python lists/dicts is:
+```python
+rules = [
+# expiration_days < 5 AND current_inventory > 20
+{ "conditions": { "all": [
+ { "name": "expiration_days",
+ "operator": "less_than",
+ "value": 5,
+ },
+ { "name": "current_inventory",
+ "operator": "greater_than",
+ "value": 20,
+ },
+ ]},
+ "actions": [
+ { "name": "put_on_sale",
+ "params": {"sale_percentage": 0.25},
+ },
+ ],
+},
+# current_inventory < 5 OR (current_month = "December" AND current_inventory < 20)
+{ "conditions": { "any": [
+ { "name": "current_inventory",
+ "operator": "less_than",
+ "value": 5,
+ },
+ ]},
+ { "all": [
+ { "name": "current_month",
+ "operator": "equal_to",
+ "value": "December",
+ },
+ { "name": "current_inventory",
+ "operator": "less_than",
+ "value": 20,
+ }
+ ]},
+ },
+ "actions": [
+ { "name": "order_more",
+ "params":{"number_to_order": 40},
+ },
+ ],
+}]
+```
+### Export the available variables, operators and actions
+To e.g. send to your client so it knows how to build rules
+```python
+from business_rules import export_rule_data
+export_rule_data(ProductVariables, ProductActions)
+```
+that returns
+```python
+{"variables": [
+ { "name": "expiration_days",
+ "label": "Days until expiration",
+ "field_type": "numeric",
+ "options": []},
+ { "name": "current_month",
+ "label": "Current Month",
+ "field_type": "string",
+ "options": []},
+ { "name": "goes_well_with",
+ "label": "Goes Well With",
+ "field_type": "select",
+ "options": ["Eggnog", "Cookies", "Beef Jerkey"]}
+ ],
+ "actions": [
+ { "name": "put_on_sale",
+ "label": "Put On Sale",
+ "params": {"sale_percentage": "numeric"}},
+ { "name": "order_more",
+ "label": "Order More",
+ "params": {"number_to_order": "numeric"}}
+ ],
+ "variable_type_operators": {
+ "numeric": [ {"name": "equal_to",
+ "label": "Equal To",
+ "input_type": "numeric"},
+ {"name": "less_than",
+ "label": "Less Than",
+ "input_type": "numeric"},
+ {"name": "greater_than",
+ "label": "Greater Than",
+ "input_type": "numeric"}],
+ "string": [ { "name": "equal_to",
+ "label": "Equal To",
+ "input_type": "text"},
+ { "name": "non_empty",
+ "label": "Non Empty",
+ "input_type": "none"}]
+ }
+}
+```
+### Run your rules
+```python
+from business_rules import run_all
+rules = _some_function_to_receive_from_client()
+for product in Products.objects.all():
+ run_all(rule_list=rules,
+ defined_variables=ProductVariables(product),
+ defined_actions=ProductActions(product),
+ stop_on_first_trigger=True
+ )
+```
+## API
+#### Variable Types and Decorators:
+The type represents the type of the value that will be returned for the variable and is necessary since there are different available comparison operators for different types, and the front-end that's generating the rules needs to know which operators are available.
+All decorators can optionally take a label:
+- `label` - A human-readable label to show on the frontend. By default we just split the variable name on underscores and capitalize the words.
+The available types and decorators are:
+**numeric** - an integer, float, or python Decimal.
+`@numeric_rule_variable` operators:
+* `equal_to`
+* `greater_than`
+* `less_than`
+* `greater_than_or_equal_to`
+* `less_than_or_equal_to`
+Note: to compare floating point equality we just check that the difference is less than some small epsilon
+**string** - a python bytestring or unicode string.
+`@string_rule_variable` operators:
+* `equal_to`
+* `starts_with`
+* `ends_with`
+* `contains`
+* `matches_regex`
+* `non_empty`
+**boolean** - a True or False value.
+`@boolean_rule_variable` operators:
+* `is_true`
+* `is_false`
+**select** - a set of values, where the threshold will be a single item.
+`@select_rule_variable` operators:
+* `contains`
+* `does_not_contain`
+**select_multiple** - a set of values, where the threshold will be a set of items.
+`@select_multiple_rule_variable` operators:
+* `contains_all`
+* `is_contained_by`
+* `shares_at_least_one_element_with`
+* `shares_exactly_one_element_with`
+* `shares_no_elements_with`
+### Returning data to your client
+## Contributing
+Open up a pull request, making sure to add tests for any new functionality. To set up the dev environment (assuming you're using [virtualenvwrapper](http://docs.python-guide.org/en/latest/dev/virtualenvs/#virtualenvwrapper)):
+```bash
+$ python -m virtualenv venv
+$ source ./venv/bin/activate
+$ pip install -r dev-requirements.txt -e .
+$ pytest
+```
+Alternatively, you can also use Tox:
+```bash
+$ pip install "tox<4"
+$ tox -p auto --skip-missing-interpreters
+```
+
+%package -n python3-business-rules
+Summary: Python DSL for setting up business intelligence rules that can be configured without code
+Provides: python-business-rules
+BuildRequires: python3-devel
+BuildRequires: python3-setuptools
+BuildRequires: python3-pip
+%description -n python3-business-rules
+As a software system grows in complexity and usage, it can become burdensome if
+every change to the logic/behavior of the system also requires you to write and
+deploy new code. The goal of this business rules engine is to provide a simple
+interface allowing anyone to capture new rules and logic defining the behavior
+of a system, and a way to then process those rules on the backend.
+You might, for example, find this is a useful way for analysts to define
+marketing logic around when certain customers or items are eligible for a
+discount or to automate emails after users enter a certain state or go through
+a particular sequence of events.
+## Usage
+### 1. Define Your set of variables
+Variables represent values in your system, usually the value of some particular object. You create rules by setting threshold conditions such that when a variable is computed that triggers the condition some action is taken.
+You define all the available variables for a certain kind of object in your code, and then later dynamically set the conditions and thresholds for those.
+For example:
+```python
+class ProductVariables(BaseVariables):
+ def __init__(self, product):
+ self.product = product
+ @numeric_rule_variable
+ def current_inventory(self):
+ return self.product.current_inventory
+ @numeric_rule_variable(label='Days until expiration')
+ def expiration_days(self)
+ last_order = self.product.orders[-1]
+ return (last_order.expiration_date - datetime.date.today()).days
+ @string_rule_variable()
+ def current_month(self):
+ return datetime.datetime.now().strftime("%B")
+ @select_rule_variable(options=Products.top_holiday_items())
+ def goes_well_with(self):
+ return products.related_products
+```
+### 2. Define your set of actions
+These are the actions that are available to be taken when a condition is triggered.
+For example:
+```python
+class ProductActions(BaseActions):
+ def __init__(self, product):
+ self.product = product
+ @rule_action(params={"sale_percentage": FIELD_NUMERIC})
+ def put_on_sale(self, sale_percentage):
+ self.product.price = (1.0 - sale_percentage) * self.product.price
+ self.product.save()
+ @rule_action(params={"number_to_order": FIELD_NUMERIC})
+ def order_more(self, number_to_order):
+ ProductOrder.objects.create(product_id=self.product.id,
+ quantity=number_to_order)
+```
+If you need a select field for an action parameter, another -more verbose- syntax is available:
+```python
+class ProductActions(BaseActions):
+ def __init__(self, product):
+ self.product = product
+ @rule_action(params=[{'fieldType': FIELD_SELECT,
+ 'name': 'stock_state',
+ 'label': 'Stock state',
+ 'options': [
+ {'label': 'Available', 'name': 'available'},
+ {'label': 'Last items', 'name': 'last_items'},
+ {'label': 'Out of stock', 'name': 'out_of_stock'}
+ ]}])
+ def change_stock_state(self, stock_state):
+ self.product.stock_state = stock_state
+ self.product.save()
+```
+### 3. Build the rules
+A rule is just a JSON object that gets interpreted by the business-rules engine.
+Note that the JSON is expected to be auto-generated by a UI, which makes it simple for anyone to set and tweak business rules without knowing anything about the code. The javascript library used for generating these on the web can be found [here](https://github.com/venmo/business-rules-ui).
+An example of the resulting python lists/dicts is:
+```python
+rules = [
+# expiration_days < 5 AND current_inventory > 20
+{ "conditions": { "all": [
+ { "name": "expiration_days",
+ "operator": "less_than",
+ "value": 5,
+ },
+ { "name": "current_inventory",
+ "operator": "greater_than",
+ "value": 20,
+ },
+ ]},
+ "actions": [
+ { "name": "put_on_sale",
+ "params": {"sale_percentage": 0.25},
+ },
+ ],
+},
+# current_inventory < 5 OR (current_month = "December" AND current_inventory < 20)
+{ "conditions": { "any": [
+ { "name": "current_inventory",
+ "operator": "less_than",
+ "value": 5,
+ },
+ ]},
+ { "all": [
+ { "name": "current_month",
+ "operator": "equal_to",
+ "value": "December",
+ },
+ { "name": "current_inventory",
+ "operator": "less_than",
+ "value": 20,
+ }
+ ]},
+ },
+ "actions": [
+ { "name": "order_more",
+ "params":{"number_to_order": 40},
+ },
+ ],
+}]
+```
+### Export the available variables, operators and actions
+To e.g. send to your client so it knows how to build rules
+```python
+from business_rules import export_rule_data
+export_rule_data(ProductVariables, ProductActions)
+```
+that returns
+```python
+{"variables": [
+ { "name": "expiration_days",
+ "label": "Days until expiration",
+ "field_type": "numeric",
+ "options": []},
+ { "name": "current_month",
+ "label": "Current Month",
+ "field_type": "string",
+ "options": []},
+ { "name": "goes_well_with",
+ "label": "Goes Well With",
+ "field_type": "select",
+ "options": ["Eggnog", "Cookies", "Beef Jerkey"]}
+ ],
+ "actions": [
+ { "name": "put_on_sale",
+ "label": "Put On Sale",
+ "params": {"sale_percentage": "numeric"}},
+ { "name": "order_more",
+ "label": "Order More",
+ "params": {"number_to_order": "numeric"}}
+ ],
+ "variable_type_operators": {
+ "numeric": [ {"name": "equal_to",
+ "label": "Equal To",
+ "input_type": "numeric"},
+ {"name": "less_than",
+ "label": "Less Than",
+ "input_type": "numeric"},
+ {"name": "greater_than",
+ "label": "Greater Than",
+ "input_type": "numeric"}],
+ "string": [ { "name": "equal_to",
+ "label": "Equal To",
+ "input_type": "text"},
+ { "name": "non_empty",
+ "label": "Non Empty",
+ "input_type": "none"}]
+ }
+}
+```
+### Run your rules
+```python
+from business_rules import run_all
+rules = _some_function_to_receive_from_client()
+for product in Products.objects.all():
+ run_all(rule_list=rules,
+ defined_variables=ProductVariables(product),
+ defined_actions=ProductActions(product),
+ stop_on_first_trigger=True
+ )
+```
+## API
+#### Variable Types and Decorators:
+The type represents the type of the value that will be returned for the variable and is necessary since there are different available comparison operators for different types, and the front-end that's generating the rules needs to know which operators are available.
+All decorators can optionally take a label:
+- `label` - A human-readable label to show on the frontend. By default we just split the variable name on underscores and capitalize the words.
+The available types and decorators are:
+**numeric** - an integer, float, or python Decimal.
+`@numeric_rule_variable` operators:
+* `equal_to`
+* `greater_than`
+* `less_than`
+* `greater_than_or_equal_to`
+* `less_than_or_equal_to`
+Note: to compare floating point equality we just check that the difference is less than some small epsilon
+**string** - a python bytestring or unicode string.
+`@string_rule_variable` operators:
+* `equal_to`
+* `starts_with`
+* `ends_with`
+* `contains`
+* `matches_regex`
+* `non_empty`
+**boolean** - a True or False value.
+`@boolean_rule_variable` operators:
+* `is_true`
+* `is_false`
+**select** - a set of values, where the threshold will be a single item.
+`@select_rule_variable` operators:
+* `contains`
+* `does_not_contain`
+**select_multiple** - a set of values, where the threshold will be a set of items.
+`@select_multiple_rule_variable` operators:
+* `contains_all`
+* `is_contained_by`
+* `shares_at_least_one_element_with`
+* `shares_exactly_one_element_with`
+* `shares_no_elements_with`
+### Returning data to your client
+## Contributing
+Open up a pull request, making sure to add tests for any new functionality. To set up the dev environment (assuming you're using [virtualenvwrapper](http://docs.python-guide.org/en/latest/dev/virtualenvs/#virtualenvwrapper)):
+```bash
+$ python -m virtualenv venv
+$ source ./venv/bin/activate
+$ pip install -r dev-requirements.txt -e .
+$ pytest
+```
+Alternatively, you can also use Tox:
+```bash
+$ pip install "tox<4"
+$ tox -p auto --skip-missing-interpreters
+```
+
+%package help
+Summary: Development documents and examples for business-rules
+Provides: python3-business-rules-doc
+%description help
+As a software system grows in complexity and usage, it can become burdensome if
+every change to the logic/behavior of the system also requires you to write and
+deploy new code. The goal of this business rules engine is to provide a simple
+interface allowing anyone to capture new rules and logic defining the behavior
+of a system, and a way to then process those rules on the backend.
+You might, for example, find this is a useful way for analysts to define
+marketing logic around when certain customers or items are eligible for a
+discount or to automate emails after users enter a certain state or go through
+a particular sequence of events.
+## Usage
+### 1. Define Your set of variables
+Variables represent values in your system, usually the value of some particular object. You create rules by setting threshold conditions such that when a variable is computed that triggers the condition some action is taken.
+You define all the available variables for a certain kind of object in your code, and then later dynamically set the conditions and thresholds for those.
+For example:
+```python
+class ProductVariables(BaseVariables):
+ def __init__(self, product):
+ self.product = product
+ @numeric_rule_variable
+ def current_inventory(self):
+ return self.product.current_inventory
+ @numeric_rule_variable(label='Days until expiration')
+ def expiration_days(self)
+ last_order = self.product.orders[-1]
+ return (last_order.expiration_date - datetime.date.today()).days
+ @string_rule_variable()
+ def current_month(self):
+ return datetime.datetime.now().strftime("%B")
+ @select_rule_variable(options=Products.top_holiday_items())
+ def goes_well_with(self):
+ return products.related_products
+```
+### 2. Define your set of actions
+These are the actions that are available to be taken when a condition is triggered.
+For example:
+```python
+class ProductActions(BaseActions):
+ def __init__(self, product):
+ self.product = product
+ @rule_action(params={"sale_percentage": FIELD_NUMERIC})
+ def put_on_sale(self, sale_percentage):
+ self.product.price = (1.0 - sale_percentage) * self.product.price
+ self.product.save()
+ @rule_action(params={"number_to_order": FIELD_NUMERIC})
+ def order_more(self, number_to_order):
+ ProductOrder.objects.create(product_id=self.product.id,
+ quantity=number_to_order)
+```
+If you need a select field for an action parameter, another -more verbose- syntax is available:
+```python
+class ProductActions(BaseActions):
+ def __init__(self, product):
+ self.product = product
+ @rule_action(params=[{'fieldType': FIELD_SELECT,
+ 'name': 'stock_state',
+ 'label': 'Stock state',
+ 'options': [
+ {'label': 'Available', 'name': 'available'},
+ {'label': 'Last items', 'name': 'last_items'},
+ {'label': 'Out of stock', 'name': 'out_of_stock'}
+ ]}])
+ def change_stock_state(self, stock_state):
+ self.product.stock_state = stock_state
+ self.product.save()
+```
+### 3. Build the rules
+A rule is just a JSON object that gets interpreted by the business-rules engine.
+Note that the JSON is expected to be auto-generated by a UI, which makes it simple for anyone to set and tweak business rules without knowing anything about the code. The javascript library used for generating these on the web can be found [here](https://github.com/venmo/business-rules-ui).
+An example of the resulting python lists/dicts is:
+```python
+rules = [
+# expiration_days < 5 AND current_inventory > 20
+{ "conditions": { "all": [
+ { "name": "expiration_days",
+ "operator": "less_than",
+ "value": 5,
+ },
+ { "name": "current_inventory",
+ "operator": "greater_than",
+ "value": 20,
+ },
+ ]},
+ "actions": [
+ { "name": "put_on_sale",
+ "params": {"sale_percentage": 0.25},
+ },
+ ],
+},
+# current_inventory < 5 OR (current_month = "December" AND current_inventory < 20)
+{ "conditions": { "any": [
+ { "name": "current_inventory",
+ "operator": "less_than",
+ "value": 5,
+ },
+ ]},
+ { "all": [
+ { "name": "current_month",
+ "operator": "equal_to",
+ "value": "December",
+ },
+ { "name": "current_inventory",
+ "operator": "less_than",
+ "value": 20,
+ }
+ ]},
+ },
+ "actions": [
+ { "name": "order_more",
+ "params":{"number_to_order": 40},
+ },
+ ],
+}]
+```
+### Export the available variables, operators and actions
+To e.g. send to your client so it knows how to build rules
+```python
+from business_rules import export_rule_data
+export_rule_data(ProductVariables, ProductActions)
+```
+that returns
+```python
+{"variables": [
+ { "name": "expiration_days",
+ "label": "Days until expiration",
+ "field_type": "numeric",
+ "options": []},
+ { "name": "current_month",
+ "label": "Current Month",
+ "field_type": "string",
+ "options": []},
+ { "name": "goes_well_with",
+ "label": "Goes Well With",
+ "field_type": "select",
+ "options": ["Eggnog", "Cookies", "Beef Jerkey"]}
+ ],
+ "actions": [
+ { "name": "put_on_sale",
+ "label": "Put On Sale",
+ "params": {"sale_percentage": "numeric"}},
+ { "name": "order_more",
+ "label": "Order More",
+ "params": {"number_to_order": "numeric"}}
+ ],
+ "variable_type_operators": {
+ "numeric": [ {"name": "equal_to",
+ "label": "Equal To",
+ "input_type": "numeric"},
+ {"name": "less_than",
+ "label": "Less Than",
+ "input_type": "numeric"},
+ {"name": "greater_than",
+ "label": "Greater Than",
+ "input_type": "numeric"}],
+ "string": [ { "name": "equal_to",
+ "label": "Equal To",
+ "input_type": "text"},
+ { "name": "non_empty",
+ "label": "Non Empty",
+ "input_type": "none"}]
+ }
+}
+```
+### Run your rules
+```python
+from business_rules import run_all
+rules = _some_function_to_receive_from_client()
+for product in Products.objects.all():
+ run_all(rule_list=rules,
+ defined_variables=ProductVariables(product),
+ defined_actions=ProductActions(product),
+ stop_on_first_trigger=True
+ )
+```
+## API
+#### Variable Types and Decorators:
+The type represents the type of the value that will be returned for the variable and is necessary since there are different available comparison operators for different types, and the front-end that's generating the rules needs to know which operators are available.
+All decorators can optionally take a label:
+- `label` - A human-readable label to show on the frontend. By default we just split the variable name on underscores and capitalize the words.
+The available types and decorators are:
+**numeric** - an integer, float, or python Decimal.
+`@numeric_rule_variable` operators:
+* `equal_to`
+* `greater_than`
+* `less_than`
+* `greater_than_or_equal_to`
+* `less_than_or_equal_to`
+Note: to compare floating point equality we just check that the difference is less than some small epsilon
+**string** - a python bytestring or unicode string.
+`@string_rule_variable` operators:
+* `equal_to`
+* `starts_with`
+* `ends_with`
+* `contains`
+* `matches_regex`
+* `non_empty`
+**boolean** - a True or False value.
+`@boolean_rule_variable` operators:
+* `is_true`
+* `is_false`
+**select** - a set of values, where the threshold will be a single item.
+`@select_rule_variable` operators:
+* `contains`
+* `does_not_contain`
+**select_multiple** - a set of values, where the threshold will be a set of items.
+`@select_multiple_rule_variable` operators:
+* `contains_all`
+* `is_contained_by`
+* `shares_at_least_one_element_with`
+* `shares_exactly_one_element_with`
+* `shares_no_elements_with`
+### Returning data to your client
+## Contributing
+Open up a pull request, making sure to add tests for any new functionality. To set up the dev environment (assuming you're using [virtualenvwrapper](http://docs.python-guide.org/en/latest/dev/virtualenvs/#virtualenvwrapper)):
+```bash
+$ python -m virtualenv venv
+$ source ./venv/bin/activate
+$ pip install -r dev-requirements.txt -e .
+$ pytest
+```
+Alternatively, you can also use Tox:
+```bash
+$ pip install "tox<4"
+$ tox -p auto --skip-missing-interpreters
+```
+
+%prep
+%autosetup -n business-rules-1.1.1
+
+%build
+%py3_build
+
+%install
+%py3_install
+install -d -m755 %{buildroot}/%{_pkgdocdir}
+if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi
+if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi
+if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi
+if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi
+pushd %{buildroot}
+if [ -d usr/lib ]; then
+ find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/lib64 ]; then
+ find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/bin ]; then
+ find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/sbin ]; then
+ find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+touch doclist.lst
+if [ -d usr/share/man ]; then
+ find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst
+fi
+popd
+mv %{buildroot}/filelist.lst .
+mv %{buildroot}/doclist.lst .
+
+%files -n python3-business-rules -f filelist.lst
+%dir %{python3_sitelib}/*
+
+%files help -f doclist.lst
+%{_docdir}/*
+
+%changelog
+* Tue Apr 11 2023 Python_Bot <Python_Bot@openeuler.org> - 1.1.1-1
+- Package Spec generated
diff --git a/sources b/sources
new file mode 100644
index 0000000..6acc279
--- /dev/null
+++ b/sources
@@ -0,0 +1 @@
+4459427d78c373f60a4f08754874ff17 business-rules-1.1.1.tar.gz