Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow glob patterns instead of parent dirs for matching configs #156

Merged
merged 2 commits into from
Dec 3, 2020

Conversation

Kronuz
Copy link
Contributor

@Kronuz Kronuz commented Nov 18, 2020

Summary

Allow using globs as configuration for rules, not only parent directories.

This allows for creating specific rules for specific files, not only directories. For example:

{
    "*/urls.py": {
        "rules": [
            ["*", "deny"]
        ]
    }
}

Will allow specifying rules for all urls modules anywhere.


This also allows specifying if the allow or deny rule are meant for global or local scopes only:

{
    "*/urls.py": {
        "rules": [
            ["common.*", "allow"],
            ["*", "deny global"]
        ],
        "message": "Module in {current_file} only allows certain global imports. {imported} cannot be imported here."
    }
}

Allowing to import common.* anywhere and everything else only inside functions, as inner imports.

Test Plan

Run tests

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Nov 18, 2020
Copy link
Contributor

@jimmylai jimmylai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are lint errors.

fixit/rules/import_constraints.py Show resolved Hide resolved
@Kronuz Kronuz force-pushed the Kronuz-globs branch 2 times, most recently from ae2c12e to 2651106 Compare November 18, 2020 17:52
@jimmylai
Copy link
Contributor

The CI builds has a test case failure.
https://github.com/Instagram/Fixit/pull/156/checks?check_run_id=1419755011

It looks like a bug in the new version of LibCST related to the new Assignment/Access changes. CC @zsol

It changes b = [a for a in [1,2,3]] as b = [cls for a in [1,2,3]] which is wrong. The local access of a in the comprehension should refer to the local definition of var a in the comprehension.

@Kronuz Kronuz force-pushed the Kronuz-globs branch 2 times, most recently from 2651106 to 06cd4ac Compare December 1, 2020 22:37
@jimmylai
Copy link
Contributor

jimmylai commented Dec 1, 2020

@Kronuz there is a type check error regarding fnmatch.
https://github.com/Instagram/Fixit/pull/156/checks?check_run_id=1483019512

@codecov-io
Copy link

codecov-io commented Dec 2, 2020

Codecov Report

Merging #156 (93e1c49) into master (6e662b2) will increase coverage by 0.08%.
The diff coverage is 95.55%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #156      +/-   ##
==========================================
+ Coverage   84.71%   84.80%   +0.08%     
==========================================
  Files          86       86              
  Lines        3532     3566      +34     
==========================================
+ Hits         2992     3024      +32     
- Misses        540      542       +2     
Impacted Files Coverage Δ
fixit/common/testing.py 92.30% <50.00%> (-0.96%) ⬇️
fixit/rules/import_constraints.py 92.52% <97.61%> (+0.92%) ⬆️
fixit/common/utils.py 92.03% <100.00%> (+0.07%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 6e662b2...93e1c49. Read the comment docs.

@Kronuz Kronuz force-pushed the Kronuz-globs branch 3 times, most recently from 6f6b652 to d413093 Compare December 2, 2020 00:38
@Kronuz Kronuz requested a review from jimmylai December 2, 2020 00:49
Comment on lines 30 to 51
class Action(Enum):
ALLOW = "allow" # allow everywhere
DENY = "deny" # deny everywhere
ALLOW_GLOBAL = "allow_global" # allow in global scope
ALLOW_LOCAL = "allow_local" # allow in local scopes
DENY_GLOBAL = "deny_global" # deny in global scope
DENY_LOCAL = "deny_local" # deny in local scopes


ACTIONS_MAP: Dict[str, Action] = {
"allow": Action.ALLOW,
"deny": Action.DENY,
"allow global": Action.ALLOW_GLOBAL,
"allow local": Action.ALLOW_LOCAL,
"deny global": Action.DENY_GLOBAL,
"deny local": Action.DENY_LOCAL,
# Aliases:
"allow globally": Action.ALLOW_GLOBAL,
"allow locally": Action.ALLOW_LOCAL,
"deny globally": Action.DENY_GLOBAL,
"deny locally": Action.DENY_LOCAL,
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACTIONS_MAP looks duplicated.
To check a string is a valid Enum class attribute, just do action in Action.__members__.
To get the enum value from a string, simply do Action[action]

Suggested change
class Action(Enum):
ALLOW = "allow" # allow everywhere
DENY = "deny" # deny everywhere
ALLOW_GLOBAL = "allow_global" # allow in global scope
ALLOW_LOCAL = "allow_local" # allow in local scopes
DENY_GLOBAL = "deny_global" # deny in global scope
DENY_LOCAL = "deny_local" # deny in local scopes
ACTIONS_MAP: Dict[str, Action] = {
"allow": Action.ALLOW,
"deny": Action.DENY,
"allow global": Action.ALLOW_GLOBAL,
"allow local": Action.ALLOW_LOCAL,
"deny global": Action.DENY_GLOBAL,
"deny local": Action.DENY_LOCAL,
# Aliases:
"allow globally": Action.ALLOW_GLOBAL,
"allow locally": Action.ALLOW_LOCAL,
"deny globally": Action.DENY_GLOBAL,
"deny locally": Action.DENY_LOCAL,
}
class Action(Enum):
ALLOW = "allow" # allow everywhere
DENY = "deny" # deny everywhere
ALLOW_GLOBAL = "allow_global" # allow in global scope
ALLOW_LOCAL = "allow_local" # allow in local scopes
DENY_GLOBAL = "deny_global" # deny in global scope
DENY_LOCAL = "deny_local" # deny in local scopes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the idea behind the map was to also allow other aliases (such as "allow globally", "allow global", and "allow_global"). But yes, we can use the simple Enum, if we don't want that support.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not supporting different alias doesn't seem to be a big issue. It can also keep the config more consistent.

Comment on lines 75 to 79
if action not in ACTIONS_MAP:
raise ValueError(
"A rule should either allow or deny a pattern (possibly globally or locally)"
)
return _ImportRule(module, ACTIONS_MAP[action])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if action not in ACTIONS_MAP:
raise ValueError(
"A rule should either allow or deny a pattern (possibly globally or locally)"
)
return _ImportRule(module, ACTIONS_MAP[action])
if action not in Action.__members__:
raise ValueError(
f"A rule should have a valid action ({list(Action.__members__)})"
)
return _ImportRule(module, Action[action])

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could make this whole block even simpler if we don't want that map for aliases, albeit with a more generic error (ValueError: 'invalid_action' is not a valid RuleAction):

            return _ImportRule(module, Action(action))

fixit/rules/import_constraints.py Show resolved Hide resolved
Comment on lines 119 to 125
if test_case.message is not None and test_case.message != report.message:
raise AssertionError(
f"Expected message:\n {test_case.message}\nBut got:\n {report.message}"
)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The message in InvalidTestCase is only used in one of the new test case. Do we really need to add this new field?
Ideally, the test case example code should explain itself clearly. The example code can also have some comments to explain it better. I'd suggest not to add InvalidTestCase.message to keep it simpler.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to test the custom messages are working, not only show they exist. This allows testing custom messages and it doesn't add much complexity, only a new field that can be tested. we could call the field "expected_message" though. What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, expected_message is a better name. I can see it can be useful for rules provide custom messages.

Copy link
Contributor

@jimmylai jimmylai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM
When releasing this, we need to update existing config file to avoid the new RuleAction value error.

@Kronuz
Copy link
Contributor Author

Kronuz commented Dec 3, 2020

LGTM
When releasing this, we need to update existing config file to avoid the new RuleAction value error.

What do you mean?

@jimmylai
Copy link
Contributor

jimmylai commented Dec 3, 2020

LGTM
When releasing this, we need to update existing config file to avoid the new RuleAction value error.

What do you mean?

I read it wrong, so there won't be value error since we keep the lower case allow/deny. We can review existing rule to see if we need to refine them.

@Kronuz Kronuz merged commit b3624f5 into master Dec 3, 2020
@lpetre lpetre deleted the Kronuz-globs branch January 6, 2022 21:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants